stm32笔记汇总第一波驱动流水灯按键所做的努力.docx

上传人:b****5 文档编号:8400507 上传时间:2023-01-31 格式:DOCX 页数:14 大小:299.57KB
下载 相关 举报
stm32笔记汇总第一波驱动流水灯按键所做的努力.docx_第1页
第1页 / 共14页
stm32笔记汇总第一波驱动流水灯按键所做的努力.docx_第2页
第2页 / 共14页
stm32笔记汇总第一波驱动流水灯按键所做的努力.docx_第3页
第3页 / 共14页
stm32笔记汇总第一波驱动流水灯按键所做的努力.docx_第4页
第4页 / 共14页
stm32笔记汇总第一波驱动流水灯按键所做的努力.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

stm32笔记汇总第一波驱动流水灯按键所做的努力.docx

《stm32笔记汇总第一波驱动流水灯按键所做的努力.docx》由会员分享,可在线阅读,更多相关《stm32笔记汇总第一波驱动流水灯按键所做的努力.docx(14页珍藏版)》请在冰豆网上搜索。

stm32笔记汇总第一波驱动流水灯按键所做的努力.docx

stm32笔记汇总第一波驱动流水灯按键所做的努力

第一波驱动流水灯、按键所做的努力

一名词点击

1接口:

IIC,SPI,SDIO,USART,CAN,USB,ADC,PS2

2通信协议

3铁电存储器FRAM

(stm32开发板资源丰富,有各种接口资源部和相关通信协议,这些陌生的名词是要逐渐摸索掌握的。

二开发板模块

电源模块

下载仿真调试模块

显示模块

红外接收模块

温度采集模块

无线收发模块

AD转换模块

CAN总线模块

JLINK程序下载调试模块

无线通信模块

(学习开发板,除了掌握主控芯片的知识,更重要的是外围电路的设计,如何用主控芯片去操作外围电路模块。

疑问1:

DB9型RS232接口,分别接stm32的USART1,USART2,两个USART的作用,USB/CAN接口选择,boot调节按钮是怎么回事?

得看开发板原理图

疑问2:

ISP在系统编程是怎么回事?

如有必要,知道ISP和IAP区别。

ISP是在系统编程,就是不用拆下芯片,不用编程器,通过ISP接口线将整个程序写入到芯片中。

而IAP是在应用编程,IAP技术是从结构上将Flash存储器映射为两个存储体,当运行一个存储体上的用户程序时,可对另一个存储体重新编程,之后将程序从一个存储体转向另一个。

(这个我也搞不太清楚。

疑问3:

板载JTAG调试接口,有SWD和JTAG两种方式进行程序调试。

SWD和JTAG区别?

请搜索:

SWD与JTAG区别及使用情况

三stm32微控制器

中断间的延迟时间降到只需6个CPU周期

从低功耗模式唤醒的时间只需6个CPU周期

2.0到3.6V的供电电压范围。

玩转STM32三种低功耗模式(休眠,停机,待机)(从停机模式唤醒<7μs,从待机模式唤醒55μs)

疑问4:

LQPF100封装芯片的最小系统只需要7个外部无源器件,哪7个?

这个还是等学到stm32最小系统设计时再解决吧。

疑问5:

MISRAC?

MISRAC是由汽车产业软件可靠性协会(MISRA)提出的C语言开发标准。

其目的是在增进嵌入式系统的安全性及可移植性。

针对C++语言也有对应的标准MISRAC++。

MISRAC一开始主要是针对汽车产业,不过其他产业也逐渐开始使用MISRAC:

包括航太、电信、国防、医疗设备、铁路等领域中都已有厂商使用MISRAC。

MISRAC的第一版《GuidelinesfortheuseoftheClanguageinvehiclebasedsoftware》是在1998年发行,一般称为MISRA-C:

1998。

MISRA-C:

1998有127项规则,规则从1号编号到127号,其中有93项是强制要求,其余的34项是推荐使用的规则。

在2004年时发行了第二版的MISRAC的第一版《GuidelinesfortheuseoftheClanguageincriticalsystems》(或称作MISRA-C:

2004),其中有许多重要建议事项的变更,其规则也重新编号。

MISRA-C:

2004有141项规则,其中121项是强制要求,其余的20项是推荐使用的规则。

规则分为21类,从“开发环境”到“运行期错误”。

四stm32F103RBT6

128KBFLASH存储器,20KB的SRAM存储器

AD测量范围:

0~3.6V

DMA:

12同道DMA控制器,支持定时器,ADC,DAC,I2S,SPI,I2C,USART

51个IO端口

定时器:

3个通用定时,1个高级定时器,2个看门狗定时器,1个STSTICK定时器

通信接口:

2个SPI接口,2个I2C接口,3个USART接口,1个USB接口,1个CAN总线接口

疑问6:

POR上电复位,PDR断电复位和可编程的电压探测器PVD?

STM32内部有一个完整的上电复位(POR)和掉电复位(PDR)电路,当供电电压达到2V时系统既能正常工作。

可编程电压监测器(PVD)

可以利用PVD对VDD电压与电源控制寄存器(PWR_CR)中的PLS[2:

0]位进行比较来监控电源,这几位选择监控电压的阀值。

通过设置PVDE位来使能PVD。

电源控制/状态寄存器(PWR_CSR)中的PVDO标志用来表明VDD是高于还是低于PVD的电压阀值。

该事件在内部连接到外部中断的第16线,如果该中断在外部中断寄存器中是使能的,该事件就会产生中断。

当VDD下降到PVD阀值以下和(或)当VDD上升到PVD阀值之上时,根据外部中断第16线的上升/下降边沿触发设置,就会产生PVD中断。

例如,这一特性可用于用于执行紧急关闭任务。

下面这张表截自STM32F103x8/B的数据手册,对上图的参数给出了具体数值:

内嵌复位和电源控制模块特性

下面对上面2张图和表格中的数据做一个简要的解释:

1)PVD=ProgrammableVotageDetector可编程电压监测器

它的作用是监视供电电压,在供电电压下降到给定的阀值以下时,产生一个中断,通知软件做紧急处理。

在给出表格的上半部分就是可编程的监视阀值数据。

当供电电压又恢复到给定的阀值以上时,也会产生一个中断,通知软件供电恢复。

供电下降的阀值与供电上升的PVD阀值有一个固定的差值,这就是表中的VPVDhyst(PVD迟滞)这个参数,通过列出的PVD阀值数据可以看到这个差别。

引入这个差值的目的是为了防止电压在阀值上下小幅抖动,而频繁地产生中断。

2)POR=PowerOnReset上电复位;PDR=PowerDownReset掉电复位。

POR的功能是在VDD电压由低向高上升越过规定的阀值之前,保持芯片复位,当越过这个阀值后的一小段时间后(图中的"滞后时间"或表中的"复位迟滞"),结束复位并取复位向量,开始执行指令。

这个阀值就是表中倒数第4行(min=1.8V,typ=1.88V,max=1.96V)。

POR的功能是在VDD电压由高向低下降越过规定的阀值后,将在芯片内部产生复位,这个阀值就是表中倒数第3行(min=1.84V,typ=1.92V,max=2.0V)。

3)可以看到POR比PDR大了0.04V,这就是表中倒数第2行,VPDRhyst(PDR迟滞)=40mV。

4)从上面的第2张图可以看到,当VDD上升越过POR阀值时,内部并不马上结束复位,而是等待一小段时间(Resettemporization),这就是表中的最后一行TRSTTEMPO,它的典型数值是2.5ms。

这个滞后时间是为了等待供电电压能够升高到最低可靠工作电压以上,我们看到POR阀值最小只有1.8V,最大也只有1.96V,都低于数据手册中给出的最低可靠工作电压2.0V,所以这个滞后时间是十分必要的,如果供电电压上升缓慢,尤其是从1.8V升到2.0V以上超过1~2.5ms,则很可能造成上电复位后MCU不能正常工作的情况。

五工程模板各文件

(我终于弄懂了为什么直接对寄存器进行操作,在编译成hex文件时,可以把寄存器翻译成相应的地址。

这是因为头文件将芯片内所有的寄存器进行了地址映射,所以当编译时,操作的寄存器名实际上相当于操作寄存器的地址。

——所谓地址映射,就是将芯片上的存储器甚至I/O等资源与地址建立一一对应的关系。

如果某地址对应着某寄存器,我们就可以运用C语言的指针来寻址并修改这个地址上的内容,从而实现修改该寄存器的内容。

不同的芯片选用不用的启动文件。

stm32f10x.h这个文件主要是把stm32的所有寄存器进行地址映射。

Core.c和Core.h是为那些以Cortex-m3内核设计SOC的芯片商设计的芯片外设提供进入M3内核的接口。

system_stm32f10x.c的功能是设置系统时钟和总线时钟。

stm32f10x_rcc.c用于配置系统时钟和外设时钟。

stm32f10x_conf.h用于管理所有库文件

Misc.c这个文件提供了外设对内核中的NVIC(中断向量控制器)的访问函数,在配置中断时,必须将这个文件加入到工程中。

stm32f10x_it.c提供M3所有中断函数的入口。

六GPIO

1GPIO的八种模式:

输入浮空、模拟输入、输入上拉、输入下拉

开漏输出、推挽输出、推挽复用功能、开漏复用功能

推挽输出:

一般应用在输出高低电平场合,高电平为3.3V,低电平为0V。

开漏输出:

一般应用在电平不匹配场合,如需要5V高电平则需要外接上拉电阻。

复用推挽输出:

如GPIO引脚用作串口输出

复用开漏输出:

如果用在IC、SMBUS这些需要线与功能的复用场合

2单IO口寄存器必须按32位字访问。

3stm32的每个IO口都由7个寄存器控制:

32位端口:

配置低寄存器GPIOx_CRL

配置高寄存器GPIOx_CRH,

输入数据寄存器GPIOx_IDR

输出数据寄存器GPIOx_ODR

位设置/清除寄存器GPIOx_BSRR

配置锁定寄存器GPIOx_LCKR

16位端口:

位清除寄存器GPIOx_BRR

4GPIO配置寄存器

端口模式位设置输出模式及速率或输入模式:

00输入模式

01输出模式,最大速度10Mhz

10输出模式,最大速度2Mhz

11输出模式,最大速度50Mhz

端口配置位对应于GPIO的8种模式:

在输入模式:

00模拟输入

01浮空输入

10上拉/下拉输入模式

11保留

在输出模式:

00通用推挽输出

01通用开漏输出

10复用功能推挽输出

11复用功能开漏输出

5端口位设置/清除寄存器(GPIOx_BSRR)

低16位是位设置:

1设置对应的ODRy为1,0对对应的ODRy位不产生影响

高16位是位清除:

1清除对应的ODRy为0,0对对应的ODRy位不产生影响

七STM32中assert_param的使用

在STM32的固件库和提供的例程中,到处都可以见到assert_param()的使用。

如果打开任何一个例程中的stm32f10x_conf.h文件,就可以看到实际上assert_param是一个宏定义;

在固件库中,它的作用就是检测传递给函数的参数是否是有效的参数。

所谓有效的参数是指满足规定范围的参数,比如某个参数的取值范围只能是小于3的正整数,如果给出的参数大于3,

则这个assert_param()可以在运行的程序调用到这个函数时报告错误,使程序员可以及时发现错误,而不必等到程序运行结果的错误而大费周折。

这是一种常见的软件技术,可以在调试阶段帮助程序员快速地排除那些明显的错误。

它确实在程序的运行上牺牲了效率(但只是在调试阶段),但在项目的开发上却帮助你提高了效率。

当你的项目开发成功,使用release模式编译之后,或在stm32f10x_conf.h文件中注释掉对USE_FULL_ASSERT的宏定义,所有的assert_param()检验都消失了,不会影响最终程序的运行效率。

#defineassert_param(expr)((expr)?

(void)0:

assert_failed((u8*)__FILE__,__LINE__))

assert_param(IS_ADC_ALL_PERIPH(ADCx));

在执行assert_param()的检验时,如果发现参数出错,它会调用函数assert_failed()向程序员报告错误,在任何一个例程中的main.c中都有这个函数的模板,如下:

voidassert_failed(uint8_t*file,uint32_tline)

{

while

(1)

{}

}

你可以按照自己使用的环境需求,添加适当的语句输出错误的信息提示,或修改这个函数做出适当的错误处理。

若是返回0,则执行后面的函数assert_failed((uint8_t*)__FILE__,__LINE__),函数的作用在库函数中有解释,用来指示出错的行数和文件。

注意:

__FILE__,__LINE__是标准库函数中的宏定义!

切记

voidassert_failed(uint8_t*file,uint32_tline);刚开始没看明白为什么加在这里,仔细一想是在头文件的函数声明。

至于函数实体呢?

我们从官方文件的模板中main.c中可以找到。

如下:

voidassert_failed(u8*file,u32line) 

{/*Usercanaddhisownimplementationtoreportthefilenameandlinenumber, 

ex:

printf("Wrongparametersvalue:

file%sonline%d\r\n",file,line)*/ 

/*Infiniteloop*/ 

while

(1){} 

}英文注释也说明了怎么应用,通过输入参数来确定位置,最简单的方法就是串口打印了,这个函数的主要思想是在输入参数有问题的时候,但是有编译不出来,它可以帮你检查参数的有效性,好处不必多言,自己领悟就行。

疑问7:

GPIO_Init()中GPIOx->CRL是如何写入到GPIOx_CRL中的?

请搜索:

零死角玩转stm32-初级篇之流水灯的前后今生

八关于STM32MDK中USE_STDPERIPH_DRIVER问题的解释

初学STM32,在RealViewMDK环境中使用STM32固件库建立工程时,初学者可能会遇到编译不通过的问题。

出现如下警告或错误提示:

  warning:

#223-D:

function"assert_param"declaredimplicitly;assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

  这时候我们需要在“TargetOptions”

中的“C/C++”选项卡中如图-2所示红框中添加USE_STDPERIPH_DRIVER、STM32F10X_HD。

这样才能使编顺利通过。

图-2

  知其然了,我们还得知其所以然。

下面就听Herison给大家一一道来。

我们知道,程序的执行是从“main.c”文件开始的,其中必须包含有头文件“stm32f10x.h”。

我们打开“stm32f10x.h”,按下“Ctrl+F”键,查找USE_STDPERIPH_DRIVER,在“FindWhat”栏中输入“USE_STDPERIPH_DRIVER”。

如图-3所示。

点击“FindNext”,出现“USE_STDPERIPH_DRIVER”对应的代码行,重复上边操作三次,第三次的时候我们能在第8296-8298行找到如图-4所示代码段。

图-3

图-4

 

  这段代码的意思是,只有用预编译指令预定义了“USE_STDPERIPH_DRIVER”,才会将"stm32f10x_conf.h"包含进“stm32f10x.h”中,从而被"main.c"用到。

这就解释了,为什么我们没有在“main.c”中包含"stm32f10x_conf.h",而在编译之后却被包含进了"main.c"中,出现如图-5所示的情况。

        "stm32f10x_conf.h"文件相当于一个开关文件,如果要用到STM32固件库驱动标准外设,则外设驱动头文件是必不可少的,如“stm32f10x_gpio.h”。

在"stm32f10x_conf.h"中我们通过代码#include"stm32f10x_gpio.h"来实现这个操作。

图-5

  说到这儿估计大家已经对“USE_STDPERIPH_DRIVER”的来龙去脉有个清晰的认识了吧?

其实单从字面意思理解就是“使用标准外设驱动”,在C/C++预定义中加入“USE_STDPERIPH_DRIVER”就是允许“使用标准外设驱动”了。

至于加入的“STM32F10X_HD“同样能在文件”stm32f10x.h“通过如上所述的方法通过功能查找来进行解释,其实它也是对于对应硬件的某些定义起开关作用罢了。

九STM32库函数中GPIO_Init的理解

STM32中GPIO的配置风格和以往研究的MCU有很大的不同,研究了好一段时间才搞通。

typedefenum

{GPIO_Mode_AIN=0x0,

GPIO_Mode_IN_FLOATING=0x04,

GPIO_Mode_IPD=0x28,

GPIO_Mode_IPU=0x48,

GPIO_Mode_Out_OD=0x14,

GPIO_Mode_Out_PP=0x10,

GPIO_Mode_AF_OD=0x1C,

GPIO_Mode_AF_PP=0x18

}GPIOMode_TypeDef;

配置一个引脚只需要4位寄存器,而上面却定义了8位,仔细研究GPIO_Init()函数后,确定为ST开发人员加上去的标识位。

0x1_的是输出标识,其他则为输入模式。

下面看一下GPIO_Init()这个函数:

voidGPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef*GPIO_InitStruct)

{

uint32_tcurrentmode=0x00,currentpin=0x00,pinpos=0x00,pos=0x00;

uint32_ttmpreg=0x00,pinmask=0x00;

/*Checktheparameters

assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));

assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));

/*----------------------------GPIOModeConfiguration-----------------------

currentmode=((uint32_t)GPIO_InitStruct->GPIO_Mode)&((uint32_t)0x0F);//屏蔽高半个字节的标识位

if((((uint32_t)GPIO_InitStruct->GPIO_Mode)&((uint32_t)0x10))!

=0x00)//判断是否为输出,0x1_

{

/*Checktheparameters

assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));

/*Outputmode

currentmode|=(uint32_t)GPIO_InitStruct->GPIO_Speed;//如果是输出,则加上相关的速度标志

}

/*----------------------------GPIOCRLConfiguration------------------------

/*Configuretheeightlowportpins

if(((uint32_t)GPIO_InitStruct->GPIO_Pin&((uint32_t)0x00FF))!

=0x00)//判断引脚是否有效

{

tmpreg=GPIOx->CRL;//读出CRL寄存器中的值,并保存

for(pinpos=0x00;pinpos<0x08;pinpos++)

{

pos=((uint32_t)0x01)<

/*Gettheportpinsposition找出引脚的位置

currentpin=(GPIO_InitStruct->GPIO_Pin)&pos;

if(currentpin==pos)

{

pos=pinpos<<2;//pos*4,因为每个引脚配置占4位

/*Clearthecorrespondinglowcontrolregisterbits

pinmask=((uint32_t)0x0F)<

tmpreg&=~pinmask;//把需要配置引脚的4位清0,其位不变

/*Writethemodeconfigurationinthecorrespondingbits

tmpreg|=(currentmode<

/*ResetthecorrespondingODRbit//如果是下拉输入或者上拉输入,则还需要配置PxODR位

if(GPIO_InitStruct->GPIO_Mode==GPIO_Mode_IPD)

{

GPIOx->BRR=(((uint32_t)0x01)<

}

else

{

/*SetthecorrespondingODRbit

if(GPIO_InitStruct->GPIO_Mode==GPIO_Mode_IPU)

{

GPIOx->BSRR=(((uint32_t)0x01)<

}

}

}

}

GPIOx->CRL=tmpreg;//把配置好的数值写入寄存器

}

十和配置LED引脚类似LED_GPIO_Config(),驱动按键也要对接按键的引脚进行配置KEY_GPIO_Config(),主要区别在于引脚的功能模式和引脚号的选择。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1