stm32之波特率USART

Posted qifeng1024

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm32之波特率USART相关的知识,希望对你有一定的参考价值。

先说一下波特率,下面抄自百度:

波特率表示每秒钟传送的码元符号的个数,是衡量数据传送速率的指标,它用单位时间内载波调制状态改变的次数来表示。  
在信息传输通道中,携带数据信息的信号单元叫码元,每秒钟通过信道传输的码元数称为码元传输速率,简称波特率。波特率是传输通道频宽的指标。 

好的,那么怎么配置波特率?

原理图如下:

技术图片

 

 

 就是用最下面这两个公式去计算和配置波特率。

配置什么东西,肯定要看看寄存器。。。

技术图片

 

 

 和上面的原理图相似,波特率分为整数和小数部分,分别把这两个和单片机的时钟带进公式,就能得到波特率了

代码如下:(M4的USART时钟波特率是84MHZ,所以下面写成84000000ul)

    usart_div = (float)84000000ul / (DEBUG_USART_BOUND * 16);
    div_mantissa = (u16)usart_div;    //得到整数部分
    div_fraction = (usart_div - div_mantissa) * 16 + 0.5;//四舍五入
    USART1->BRR = (div_mantissa << 4) + div_fraction;    //设置波特率

 

 

 

 

 

 

下面说说串口USART:

技术图片

 

 

代码如下:

 

初始化USART(本代码中顺带加入了中断;本例中引脚为PA9)

void debug_usart_init(void)
{
    float usart_div = 0;
    u16 div_mantissa = 0;
    u16 div_fraction = 0;
    
    debug_usart_port_init();
    
    RCC->APB2ENR |= (0X1 << 4);        //开启USART1的时钟

    usart_div = (float)84000000ul / (DEBUG_USART_BOUND * 16);
    div_mantissa = (u16)usart_div;    //得到整数部分
    div_fraction = (usart_div - div_mantissa) * 16 + 0.5;//四舍五入
    USART1->BRR = (div_mantissa << 4) + div_fraction;    //设置波特率
    
    USART1->CR1 = 0;//清空所有配置
    
    USART1->CR1 |= (0X1 << 3);//发送器使能
    USART1->CR1 |= (0X1 << 2);//接收器使能
    
    USART1->CR1 |= (0X1 << 13);//使能USART1
    
    USART1->CR2 &= ~(0X3 << 12);//停止位为1个位
    
    uint32_t priority = 0;        //保存合成的优先级值
    NVIC_SetPriorityGrouping(7 - 2);
    priority = NVIC_EncodePriority(7 - 2, 2, 2);
    NVIC_SetPriority(USART1_IRQn, priority);    //以USART1为例

    //根据外设寄存器配置----需要掌握该外设相关的寄存器
    USART1->CR1 |= (0X1 << 5);//接收中断使能

    NVIC_EnableIRQ(USART1_IRQn);    //以USART1为例
}

 

 

USART的中断服务函数:

void USART1_IRQHandler(void)
{
    uint8_t receive_data = 0;
    
    //如果接收到数据,产生接收标志位
    if(USART1->SR & (0x1 << 5))
    {
        USART1->SR &= ~(0x1 << 5);    //清除标志位
        
        //读取接收缓冲区中的数据
        receive_data = USART1->DR;
        
        dubug_usart_write_byte_data(receive_data);    //将接收到的字节数据发送出去
    }
}

 

 

 

 

 

发送和接受数据函数:

/*
***********************************************************************************************
* 函数功能: 发送一个字节数据
* 函数形参: writedata    需要发送的数据
* 函数返回值: None
* 备注: None
* 作者: 
* 时间: 
* 修改作者: None
* 修改时间: None
***********************************************************************************************
*/
void dubug_usart_write_byte_data(uint8_t writedata)
{
    //等待发送缓冲区空
    while(!(USART1->SR & (0X1 << 7)))
    {
        
    }
    //发送缓冲区已经空了
    
    //发送数据
    USART1->DR = writedata;
}



/*
***********************************************************************************************
* 函数功能: 接收一个字节数据
* 函数形参: None
* 函数返回值: 接收到的数据
* 备注: None
* 作者: 
* 时间: 
* 修改作者: None
* 修改时间: None
***********************************************************************************************
*/
uint8_t dubug_usart_read_byte_data(void)
{
    //等待接收缓冲区非空
    while(!(USART1->SR & (0X1 << 5)))
    {
        
    }
    //接收缓冲区非空,有数据
    
    //读取数据
    return USART1->DR;
}


/*
***********************************************************************************************
* 函数功能: 接收一串字符数据
* 函数形参: *string    用来存储接收到的字符串
* 函数返回值: None
* 备注: None
* 作者: 
* 时间: 
* 修改作者: None
* 修改时间: None
***********************************************************************************************
*/
void debug_usart_recivied_string(uint8_t *string)
{
    while(1)
    {
        //等待接收缓冲区非空
        while(!(USART1->SR & (0X1 << 5)))
        {
            
        }
        //接收缓冲区非空,有数据
        //读取数据
        *string = USART1->DR;
        
        //如果接收到的字符为‘
‘或‘
‘认为接收字符串完成
        if(*string == 
 || *string == 
)
        {
            *string = ;    //不存储‘
‘或‘
‘,存储一个字符串结束标志
            
            break;
        }
        
        string++;
    }
}

 

 

 

实现printf()功能的代码 ,直接加进去就好:

#pragma import(__use_no_semihosting_swi) //取消半主机状态

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;

int fputc(int ch, FILE *f) 
{
    while((USART1->SR &(0X01<<7))==0);  //等待之前的数据发送完毕
        USART1->DR=ch;
  return (ch);
}

int ferror(FILE *f) {
  /* Your implementation of ferror */
  return EOF;
}

void _ttywrch(int ch) {
  while((USART1->SR &(0X01<<7))==0);
        USART1->DR=ch;
}

void _sys_exit(int return_code) {
label:  goto label;  /* endless loop */
}

 

84000000

以上是关于stm32之波特率USART的主要内容,如果未能解决你的问题,请参考以下文章

STM32串口USART1的使用方法

STM32USART串口通信

STM32F103(二十三)通用同步异步收发器(USART)

在STM32板上运行后如何更改UART波特率?

STM32F103X datasheet学习笔记---USART

Stm32L151RCxxx USART 挂起问题,同时基于中断的 TX/RX