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;
        
        //如果接收到的字符为'\r'或'\n'认为接收字符串完成
        if(*string == '\r' || *string == '\n')
        {
            *string = '\0';    //不存储'\r'或'\n',存储一个字符串结束标志
            
            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
posted @ 2019-10-24 20:40  祁峰_1024  阅读(1237)  评论(0编辑  收藏  举报