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

原文地址:https://www.cnblogs.com/qifeng1024/p/11734750.html

时间: 2024-10-14 05:30:26

stm32之波特率、USART的相关文章

STM32学习笔记——USART串口(向原子哥和火哥学习)

一.USART简介 通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换.USART利用分数波特率发生器提供宽范围的波特率选择. STM32 的串口资源相当丰富的,功能也相当强劲.STM32F103ZET6 最多可提供 5 路串口,有分数波特率发生器,支持同步单向通信和半双工单线通信,支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作.它还允许多处理器通信.

STM32下波特率计算详解

波特率的计算 STM32下的波特率和串口外设时钟息息相关,USART 1的时钟来源于APB2,USART 2-5的时钟来源于APB1.在STM32中,有个波特率寄存器USART_BRR,如下: STM32串口波特率通过USART_BRR进行设置,STM32的波特率寄存器支持分数设置,以提高精确度.USART_BRR的前4位用于表示小数,后12位用于表示整数.但是它还不是我们想要设置的波特率,想要设置我们串口的波特率大小还需要进行计算.其实有关波特率的计算是下面这一条表达式: 从上面的表达式,我们

STM32 CAN 波特率设置及采样点设置

一.CAN波特率 STM32 位时间定义: ● 同步段(SYNC_SEG):通常期望位的变化发生在该时间段内.其值固定为1个时间单元(1 x tCAN).● 时间段1(BS1):定义采样点的位置.它包含CAN 标准里的 PROP_SEG 和PHASE_SEG1.其值可以编程为1 到16 个时间单元,但也可以被自动延长,以补偿因为网络中不同节点的频率差异所造成的相位的正向漂移.● 时间段2(BS2) : 定义发送点的位置.它代表CAN 标准里的PHASE_SEG2.其值可以编程为1 到8 个时间单

USART波特率计算溢出Bug

硬件平台是STM32F429,运行在 180MHz 主频下,固件库版本V1.2.1.使用 USART1 和 USART2 进行串口输出,但是用示波器一看,波特率明显不对. 我的代码如下: RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE); USART_InitStruct.USART_BaudRate = 9600; USART_

STM32的USART

一.STM32常见波特率图标. USART1是由APB2总线提供时钟,而USART2~USART5是由APB1总线提供时钟,APB1的时钟是36Mhz,比APB2总线时钟要慢一半,所以USART1实际上可以在高速一点的波特率传输的时候要比USART2~USART5稳定. 二.STM32具有硬件流控制 三.STM32与printf()函数 四.串口数据的实时性计算 注:以下是常有的串口接口:

STM32的bulk双缓冲传输速度的讨论,硬件的坑永远填不完

详情:http://bbs.21ic.com/forum.php?mod=viewthread&tid=109584 USB 1.0的最高12Mbps. USB 2.0的高速模式480Mbps,全速模式12Mbps,低速模式1.5Mbps 而是设置STM32端的USART的波特率.PC与STM32传输速度是以USB1.1的理论速度传输的,是不能设置的. 接收到数据,置NAK->将缓冲区数据拷贝到用户区(用户处理过程)->发ACK通知主机完成了完整的接收可以发送下一个->主机发送下

USART异步模式配置

特性: (1)USART只能一位一位地发送和接受数据,在起始位期间,TX端处于低电平:当闲置时,TX端为高. (2)发送和接受由一共用的波特率发生器驱动,当发送器和接收器的使能位分别置位时,分别为其产生时钟. (3)发送器根据M位的状态发送8位或9位的数据字.当发送使能位TE被置位时,发送移位寄存器中的数据从TX上输出,如果需要用到时钟,相应的时钟脉冲将在SCLK脚上输出. (4)一帧数据结构: ■起始位 ■8位或9位的数据字 ■可选的奇偶校验位 ■停止位 对于上面这张图,从下至上,我们看到串口

5.USART异步串行口输入输出(轮询模式)

学习是一个简单的过程,只要有善于发掘的眼睛,总能学到新知识,然而如何坚持不懈的学习却很困难,对我亦如此,生活中有太多的诱惑,最后只想说一句勿忘初心.闲话不多扯,本篇讲诉的是异步串行口的输入输出,串口在外设中属于比较简单的通讯模式,但是在大型项目调试中又十分重要,理解该外设模块对于以后的通讯协议学习以及软件调试都有重要意义. 通讯协议是指双方实体完成通信或服务所必须遵循的规则和约定,对于串口来说,包含波特率,数据位长度,停止位和数据校验位,当stm32芯片和客户端具有相同的协议约定时即能够正确的接

三角函数查表法和三角函数值数组生成方法

今天打算用STM32驱动TFTLCD屏显示显示一个画扇形的程序,这样就需要我们有一个画圆弧的程序,我尝试了很多方法,其中有一种方法就是使用三角函数来确定圆弧的点的坐标,即: x=radius*cos(angle); y=radius*sin(angle); 下面是当时的计算过程:我们先把角度变成弧度,我们在这里使用了ToRad()函数来实现,程序十分简单. #include <math.h> #define pi 3.141592653f int shu; float ToRad(float