武汉理工大学毕业设计(论文)
temp=RCC->CFGR>>2; temp&=0x03; } }
Stm32_Clock_Init函数只有一个变量PLL,就是用来配置时钟的倍频数的,当前所用的晶振为8Mhz,PLL的值设为9,那么STM32将运行在72M的速度下。
此外,在程序中经常用到延时函数,利用CM3内核的处理器内部包含的SysTick定时器来实现延时,它是一个24位的倒计数定时器,当记到0时,将从RELOAD寄存器中自动重装载定时初值。只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。使用SysTick来实现延时,既不占用中断,也不占用系统定时器。
4.1.2 I/O初始化
每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL,GPIOx_CRH),两个32位数据寄存器(GPIOx_IDR和GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。
GPIO端口的每个位可以由软件分别配置成多种模式: 输入浮空 、输入上拉、 输入下拉 、模拟输入、开漏输出 、推挽式输出、推挽式复用功能 、开漏复用功能。每个I/O端口位可以自由编程,然而I/0端口寄存器必须按32位字被访问(不允许半字或字节访问)。GPIOx_BSRR和GPIOx_BRR寄存器允许对任何GPIO寄存器的读/更改的独立访问;这样,在读和更改访问之间产生IRQ时不会发生危险。下图给出了一个I/O端口位的基本结构。
图4.1 I/O端口结构
11
武汉理工大学毕业设计(论文)
首先为了方便函数的编写,进行IO口的地址映射,如下(列举部分): #define
BITBAND(addr,
bitnum)
((addr
&
0xF0000000)+0x2000000+((addr
&0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) //IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
在使用IO口前需要使能相应端口的时钟,然后配置它的模式。与配置相关的两个寄存器位CRL,CRH,其结构如下所示
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16CNF7[1:0] MODE7[1:0] CNF6[1:0] MODE6[1:0] CNF5[1:0] MODE5[1:0] CNF4[1:0] MODE4[1:0] rw rw rw rw rw rw rw rw rw rw rw rw rw rw rw rw15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0CNF3[1:0] MODE3[1:0] CNF2[1:0] MODE2[1:0] CNF1[1:0] MODE1[1:0] CNF0[1:0] MODE0[1:0] rw rw rw rw rw rw rw rw rw rw rw rw rw rw rw rw位31:3027:2623:2219:1815:1411:107:63:2CNFy[1:0]:端口x配置位在输入模式下(MODE[1:0]=00):00:模拟输入模式01:浮空输入模式10:上拉/下拉输入模式11:保留在输出模式下(MODE[1:0]>00):00:通用推挽输出模式01:通用开漏输出模式10:复用功能推挽输出模式11:复用功能开漏输出模式位29:2825:2421:2017:1613:129:85:41:0MODEy[1:0];端口x的模式位00:输入模式01:输出模式,最大速度10MHZ10:输出模式,最大速度2MHZ11:输出模式,最大速度50MHZ
图4.2 CRL/CRH寄存器结构
该寄存器的复位值为0X4444 4444,从上图可以看到,复位值其实就是配置端口为浮空输入模式。从上图还可以得出:STM32的CRL控制着每个IO端口(A~G)的低8位的模式。每个IO端口的位占用CRL的4个位,高两位为CNF,低两位为MODE。这里我们可
12
武汉理工大学毕业设计(论文)
以记住几个常用的配置,比如0X0表示模拟输入模式(ADC用)、0X3表示推挽输出模式(做输出口用,50M速率)、0X8表示上/下拉输入模式(做输入口用)、0XB表示复用输出(使用IO口的第二功能,50M速率)。
CRH的作用和CRL完全一样,只是CRL控制的是低8位输出口,而CRH控制的是高8位输出口。
RCC->APB2ENR|=1<<2; //使能PORTA时钟 RCC->APB2ENR|=1<<5; //使能PORTD时钟 GPIOA->CRH&=0XFFFFFFF0;
GPIOA->CRH|=0X00000003;//PA8 推挽输出 GPIOD->CRL&=0XFFFFF0FF;
GPIOD->CRL|=0X00000300;//PD2 推挽输出 GPIOD->ODR|=1<<2; //PD2 输出高
GPIOA->ODR|=1<<8; //PA8 输出高
这里PA2与PD2分别对应LED0和LED1。此外,按键的初始化也就是对I/O进行设置,key0与key1分别对应PA13和PA15,都设置为上拉输入。
RCC->APB2ENR|=1<<2; //使能PORTA时钟 GPIOA->CRH&=0X000FFFFF;
GPIOA->CRH|=0X80800000; //PA13,15 设置为输入 GPIOA->ODR|=1<<13; //PA13上拉 GPIOA->ODR|=1<<15; //PA15上拉
4.1.3 串口初始化
本次设计中蓝牙的收发都是通过串口传至STM32内,串口最基本的设置,就是波特率的设置。STM32的串口使用需要开启了串口时钟,并设置相应IO口的模式,然后配置一下波特率,数据位长度,奇偶校验位等信息。具体步骤如下。
串口时钟使能。串口作为STM32的一个外设,其时钟由外设时钟使能寄存器控制,其中串口1是在APB2ENR寄存器的第14位。除了串口1的时钟使能在APB2ENR寄存器,其他串口的时钟使能位都在APB1ENR寄存器。
串口复位。当外设出现异常的时候可以通过复位寄存器里面的对应位设置,实现该外设的复位,然后重新配置这个外设达到让其重新工作的目的。一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。串口1的复位是通过配置APB2RSTR寄存器的第14位来实现的。
串口波特率设置。每个串口都有一个自己独立的波特率寄存器USART_BRR,通过设置该寄存器就可以达到配置不同波特率的目的。
串口控制。STM32的每个串口都有3个控制寄存器USART_CR1~3,串口的很多配置都是通过这3个寄存器来设置的。
13
武汉理工大学毕业设计(论文)
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16保留15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0保留 UE M WAKE PCE PS PEIE TXEIE TXIE RXNEIE IDLEID TE RE RWU SBK
图4.3 USART_CR寄存器各位描述
该寄存器的高18位没有用到,低14位用于串口的功能设置。UE为串口使能位,通过该位置1,以使能串口。M为字长选择位,当该位为0的时候设置串口为8个字长外加n个停止位,停止位的个数(n)是根据USART_CR2的[13:12]位设置来决定的,默认为0。PCE为校验使能位,设置为0,则禁止校验,否则使能校验。PS为校验位选择,设置为0则为偶校验,否则为奇校验。TXIE为发送缓冲区空中断使能位,设置该位为1,当USART_SR中的TXE位为1时,将产生串口中断。TCIE为发送完成中断使能位,设置该位为1,当USART_SR中的TC位为1时,将产生串口中断。RXNEIE为接收缓冲区非空中断使能,设置该位为1,当USART_SR中的ORE或者RXNE位为1时,将产生串口中断。TE为发送使能位,设置为1,将开启串口的发送功能。RE为接收使能位,用法同TE。
数据发送与接收。STM32的发送与接收是通过数据寄存器USART_DR来实现的,这是一个双寄存器,包含了TDR和RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到收据的时候,也是存在该寄存器内。该寄存器的各位描述如下图所示:
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16保留15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 保留 DR[8:0] rw rw rw rw rw rw rw rw rw 图4.4 USART_DR寄存器各位描述
串口状态。串口的状态可以通过状态寄存器USART_SR读取。USART_SR的各位描述如下图所示:
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16保留15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 保留 CTS LBD TXE TC RXNE IDLE ORE NE FE PE
图4.5 USART_SR寄存器各位描述
14
武汉理工大学毕业设计(论文)
RXNE(读数据寄存器非空),当该位被置1的时候,就是提示已经有数据被接收到了,并且可以读出来了。这时候我们要做的就是尽快去读取USART_DR,通过读USART_DR可以将该位清零,也可以向该位写0,直接清除。
TC(发送完成),当该位被置位的时候,表示USART_DR内的数据已经被发送完成了。如果设置了这个位的中断,则会产生中断。该位也有两种清零方式:1)读USART_SR,写USART_DR。2)直接向该位写0。 代码如下:
void uart_init(u32 pclk2,u32 bound) { }
float temp; u16 mantissa; u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV mantissa=temp;
//得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分 mantissa+=fraction;
RCC->APB2ENR|=1<<2; //使能PORTA口时钟 RCC->APB2ENR|=1<<14; //使能串口时钟 GPIOA->CRH&=0XFFFFF00F;//IO状态设置 GPIOA->CRH|=0X000008B0;
RCC->APB2RSTR|=1<<14; //复位串口1 RCC->APB2RSTR&=~(1<<14);//停止复位 //波特率设置
USART1->CR1|=0X200C; //1位停止,无校验位
//使能接收中断
USART1->CR1|=1<<8; //PE中断使能
USART1->CR1|=1<<5; //接收缓冲区非空中断使能 MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级
mantissa<<=4;
USART1->BRR=mantissa; //波特率设置 #if EN_USART1_RX
#endif
4.1.4 DMA初始化
DMA全称为:Direct Memory Access,即直接存储器访问。DMA传输方式无需CPU直接控制传输,也没有像中断处理方式那样保留现场和恢复现场的过程,而是通过硬件为
15
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库基于stm32的温度测量系统(4)在线全文阅读。
相关推荐: