STM32 USART

 

说到串口,自然离不开波特率,波特率又跟系统时钟有关,所以首先就先看下STM32的串口波特率怎么设置。

STM32有数个串口,每个串口都有一个自己独立的波特率寄存器USART_BRR,通过设置该寄存器就可以达到配置不同波特率的目的,由于STM32采用了分数波特率,所以STM32的串口波特率设置范围很宽,而且误差很小。

由上表可知:USART_BRR的最低4位(位[3:0])用来存放小数部分DIV_Fraction,紧接着的12位(位[15:4])用来存放整数部分DIV_Mantissa,最高16位保留。

STM32的串口波特率计算公式如下:

上式中,Fpclk是给串口的时钟(PCLK1用于USART2、3、4、5,PCLK2用于USART1,以前说过,PCLK1是由系统时钟分频得来,最大36MHZPCLK2是直接由系统时钟得来,最大72MHZ。)

USARTDIV是一个无符号定点数,我们已知要设置的波特率及系统时钟,这样就可以算出USARTDIV的值,并把它的整数和小数分离开来,分别写入USART_BRR寄存器里的对应位就行了,假设我们的串口1要设置为115200的波特率,而PCLK2的时钟为72M。这样,我们根据上面的公式有:

USARTDIV=72000000/(115200*16)=39.0625

那么得到:

DIV_Fraction=16*0.0625=1=0X01;

DIV_Mantissa= 468=0X27;

这样,我们就得到了USART1->BRR的值为0X27。只要设置串口1的BRR寄存器值为

0X27就可以得到115200的波特率。

以上是串口最重要的比特率设置,下面是串口的一些其他寄存器。

1:首先是使能串口时钟,串口作为STM32的一个外设,其时钟由外设时钟使能寄存器控制,串口1是在APB2ENR寄存器的第14位,除了串口1的时钟使能在APB2ENR寄存器,其他串口的时钟使能位都在APB1ENR寄存器。

2:复位串口,一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作。串口1的复位是通过配置APB2RSTR寄存器的第14位来实现的,通过向该位写1复位串口1,写0结束复位。其他串口的复位位在APB1RSTR里面设置。

APB2RSTR寄存器描述:

3:串口功能控制,串口控制寄存器有三个:USATR_CR1-3串口的很多配置都是通过这3个寄存器来设置的,这里我们只要用到USART_CR1就可以实现我们的功能了,该寄存器的各位描述如下图所示:

该寄存器的高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。

RWU为接收唤醒,该位用来决定是否把USART置于静默模式。软件对该位置位或者清零。当唤醒序列到来时,硬件也会将其清零。

4数据发送与接收。STM32的发送与接收是通过数据寄存器USART_DR来实现的,这是一个双寄存器,包含了TDR和RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到收据的时候,也是存在该寄存器内。该寄存器的各位描述如下图所示: 

虽然是一个32位寄存器,但是只用了低9位(DR[8:0]),其他都是保留。

DR[8:0]为串口数据,包含了发送或接收的数据。由于它是由两个寄存器组成的,一个给发送用(TDR),一个给接收用(RDR),该寄存器兼具读和写的功能。

5串口状态。串口的状态可以通过状态寄存器USART_SR读取。

这里有两个位,第5、6位RXNE和TC。

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<<=4;

mantissa+=fraction; 

RCC->APB2ENR|=1<<14;  //使能串口时钟 

GPIOA->CRH=0X444444B4;//IO状态设置

  

RCC->APB2RSTR|=1<<14;   //复位串口1

RCC->APB2RSTR&=~(1<<14);//停止复位        

//波特率设置

  USART1->BRR=mantissa; // 波特率设置  

USART1->CR1|=0X200C;  //1位停止,无校验位.

#ifdef EN_USART1_RX   //如果使能了接收

//使能接收中断

USART1->CR1|=1<<8;    //PE中断使能

USART1->CR1|=1<<5;    //接收缓冲区非空中断使能     

MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级 

#endif

}

你可能感兴趣的:(STM32,初探)