STM32学习笔记(5) 串口通讯-接收与发送

本文涉及的产品
视频直播,500GB 1个月
简介: 一个码元就是一个脉冲信号,一个脉冲信号有可能携带1bit数据,也有可能携带2bit数据、4bit数据!你发送一个脉冲信号,如果就可以携带4bit数据,肯定发送速率更快啊!

一 通信的基本概念


1.串口并行与串行


数电课讲过,并行速度快但占用的门电路多,耗费空间


串行速度慢但节约空间


2.数据通信方向


。全双工:TX,RX同时收发数据

。半双工:不能同时收发数据,可分时收发数据

。单工:任何时刻都只能往某一个固定的方向传输数据


3.数据同步方式


。同步


。异步


4.通信速率


。比特率:每秒钟传输的二进制位数,单位(bit/s)


。波特率:每秒中传输的码元个数


一个码元就是一个脉冲信号,一个脉冲信号有可能携带1bit数据,也有可能携带2bit数据、4bit数据!你发送一个脉冲信号,如果就可以携带4bit数据,肯定发送速率更快啊!


那么怎么实现一个脉冲信号就能携带多个bit数据呢?就需要一定的技术了,比如设置模拟信号中信号的频率、相位、振幅啥的。举个例子:把振幅分成四种,低(00)、中(01)、高(10)、很高(11),这样我发一个脉冲信号,它的振幅是低,那就说明发送的是00(也就是2bit),它的振幅是中(01),发送的就是01(也就是2bit)……也就实现了一个脉冲信号,携带2bit的功能…(举个不恰当的例子让大家理解而已,明白啥意思就行)


再说一次,一个码元就是一个脉冲信号!波特率指的就是1秒能发送多少个码元,也就是1秒能发送多少个脉冲信号!


一个码元能携带1bit数据,那么比特率 = 波特率!


一个码元能携带2bit数据,那么比特率 = 2倍的波特率!


一个码元能携4bit数据,那么比特率 =4倍的波特率


  • 一个二进制表示码元


0V——0


3.3V——1


  • 两个二进制表示一个码元


0V——00


3V——01


6V——10


9V——11


  • 通常情况下波特率等于比特率


二 串口通信协议


1.RS232标准


2.USB转串口


用于设备和电脑的通讯,电平转化芯片一般是CH340


3.串口到串口:串口一次只能发1个字节的数据( UART_SendByte()


三 串口数据包的组成


起始位 数据位 校验位 停止位
0 位0—位7 1


校验位


  • 奇校验


有效数据和校验位“1”总的个数为奇数


  • 偶校验


偶数


四 串口的功能框图


53624dcc1da4436daa598b72516d6b45.png


417dad7a3e0c4b70a472df6afb5b1156.png


1.引脚作用


。TX:数据发送


。RX:数据接受


。SCLK:时钟,仅同步通信使用


。nRTS:Request to send.请求发送


。nCTS:Clear to send.允许发送


2.USART:S是同步。USART1~USART3都有SCLK引脚


UART:异步。无SCLK引脚


3.数据寄存器DR


31——9 bit 8——0 bit
保留 DR[8:0]


  • 31-9 bit:保留位,始终为1
  • 8-0 bit:数据位,由TDR(发送寄存器),RDR(接收寄存器),包含发送和接受功能


五 程序流程


  • 串口初始化结构体


typedef struct
{
  uint32_t USART_BaudRate;            //波特率 BRR
  uint16_t USART_WordLength;          //字长   CR1_M
  uint16_t USART_StopBits;            //停止位 CR2_STOP 
  uint16_t USART_Parity;              //校验位 CR1_PCE CR1_PS
  uint16_t USART_Mode;                //模式选择 CR1_TE CR1_RE
  uint16_t USART_HardwareFlowControl; //硬件流选择 CR3_CTSE,CR3_RTSE
} USART_InitTypeDef;


USART_WordLength

。USART_StopBits

#define USART_StopBits_1                     ((uint16_t)0x0000)
#define USART_StopBits_0_5                   ((uint16_t)0x1000)
#define USART_StopBits_2                     ((uint16_t)0x2000)
#define USART_StopBits_1_5                   ((uint16_t)0x3000)


。USART_Parity


#define USART_Parity_No                      ((uint16_t)0x0000)
#define USART_Parity_Even                    ((uint16_t)0x0400)
#define USART_Parity_Odd                     ((uint16_t)0x0600) 


USART_Mode


#define USART_Mode_Rx                        ((uint16_t)0x0004)
#define USART_Mode_Tx                        ((uint16_t)0x0008)
#define IS_USART_MODE(MODE) ((((MODE) & (uint16_t)0xFFF3) == 0x00) && ((MODE) != (uint16_t)0x00))


。USART_HardwareFlowControl


#define USART_HardwareFlowControl_None       ((uint16_t)0x0000)
#define USART_HardwareFlowControl_RTS        ((uint16_t)0x0100)
#define USART_HardwareFlowControl_CTS        ((uint16_t)0x0200)
#define USART_HardwareFlowControl_RTS_CTS    ((uint16_t)0x0300)


硬件流功能:当外设处于准备好的状态时,硬件启动自动控制,而不需要软件再进行干预,在串口中,当串口已经准备好接收新的数据时,硬件流自动把RTS拉低;准备发送数据前,硬件流自动检查CTS是否为低(表示是否可以发送数据)。此功能需要有RTS,CTS两个引脚。


  • 同步时钟结构体


typedef struct
{
  uint16_t USART_Clock;   //同步时钟 CR2_CLKEN
  uint16_t USART_CPOL;    //极性  CR2_CPOL
  uint16_t USART_CPHA;    //相性  CR2_CPHA
  uint16_t USART_LastBit; //最后一个位的时钟脉冲 CR2_LBC
} USART_ClockInitTypeDef;


  • 流程


  1. 初始化串口需要用到的GPIO
  2. 初始化串口,USART_InitTypeDef
  3. 中断配置(接收中断,中断优先级)
  4. 使能串口
  5. 编写发送和接收函数
  6. 编写中断服务函数


  • 发送接收函数


/*
* @函数名:UART_SendByte(USART_TypeDef *p_USARTx, uint8_t ch)
* @功能:发送一个字节
* @入口参数:USARTx,ch(想发送的字节)
*/
static void UART_SendByte(USART_TypeDef *p_USARTx, uint8_t ch)
{
    /*发送一个字节的数据到USART*/
    USART_SendData(p_USARTx,ch);
    /*等待发送数据的寄存器为空*/
    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}
/*
* @函数名:UART_SendString(USART_TypeDef *p_USARTx,char *str)
* @功能:发送字符串
* @入口参数:USARTx,str(想发送的字符)
*/
void UART_SendString(USART_TypeDef *p_USARTx,char *str)
{
    unsigned int k=0;
    do
    {
        UART_SendByte(p_USARTx,*(str+k));
        k++;
    } 
    while(*(str+k) != '\0');
    /*等待发送完成*/
    while (USART_GetFlagStatus(USART1,USART_FLAG_TC)== RESET)
    {}
}


USART_FLAG_TC 与 USART_FLAG_TXE的区别:


  • USART_FLAG_TC是干嘛用的呢?


当发送移位寄存器中的1字节数据已经通过TX脚一位一位的移出去后,该标志位就会被置1,从而引发该事件的中断。所以,其实USART_FLAG_TC就是用来标志“发送移位寄存器中的数据有没有全部发送出去”这件事的。


  • USART_FLAG_TXE是干嘛用的呢?


当发送数据寄存器中的数据已经取完了,该标志位就会被置1,从而引发该事件的中断。所以,其实USART_FLAG_TXE就是用来标志一个事件的,通过它的值可以知道该事件有没有发生(即发送数据寄存器中的数据有没有被取走)。


  • 对于USART_FLAG_TXE来说,只是说明数据寄存器中的数据已经被发送移位寄存器取走了(但发送移位寄存器中可能还没有启动发送过程),通过中断就可以提醒CPU可以往数据寄存器中填充数据了,发送移位寄存器中的数据往外发送的过程其实还是比较耗时的,相对于C语言代码执行时间来说,这个过程的耗时极大,所以每次发送数据寄存器中的数据被发送移位寄存器取走后,都应该产生中断来提醒CPU对该数据寄存器填写数据;


  • 而对于USART_FLAG_TC来说,没必要每次当发送移位寄存器中的数据发送完成后都发生中断,而应该是整个串口数据帧全部发送完毕,包括最后一个字节也发送出去之后才应该开中断,这代表的就是一个数据帧发送完成事件了


六 知识重难点


  • 当数组作函数形参时,由于形参变量和实参变量是由编译系统分配的两个不同单元。在函数调用的时发生的值传送是把实参变量的值赋予给形参变量。在用数组名作函数参数的时候,不是进行值的传送,既不是把实参数组的每一个元素的值都赋予形参数组的各个元素。因为实际上形参数组并不存在,编译系统不为形参数组分配内存。那么数据的传输是如何实现的呢?数组名就是数组的首地址。因此在数组名作函数参数时所进行的传送知识地址传送,也就是说把实参数组的首地址赋予给形参数组名。形参数组取得该首地址之后,也就等于有了实在的数组。实际上,形参数组和实参数组为同一数组,共同拥有一段内存空间。


  • USART1的TX,RX通过CH340连接micro USB,所以你可以用数据线给电脑发送数据


但USART2,USART3需要额外接CH340,才能和电脑通信(PCB设计问题)


相关代码:串口的接受与发送

相关文章
|
4月前
|
传感器 编解码 API
【STM32开发入门】温湿度监测系统实战:SPI LCD显示、HAL库应用、GPIO配置、UART中断接收、ADC采集与串口通信全解析
SPI(Serial Peripheral Interface)是一种同步串行通信接口,常用于微控制器与外围设备间的数据传输。SPI LCD是指使用SPI接口与微控制器通信的液晶显示屏。这类LCD通常具有较少的引脚(通常4个:MISO、MOSI、SCK和SS),因此在引脚资源有限的系统中非常有用。通过SPI协议,微控制器可以向LCD发送命令和数据,控制显示内容和模式。
163 0
|
5月前
|
移动开发
技术好文:stm32寄存器版学习笔记06输入捕获(ETR脉冲计数)
技术好文:stm32寄存器版学习笔记06输入捕获(ETR脉冲计数)
268 0
STM32学习笔记(4) 高级定时器-两路互补的PWM输出(带死区和刹车控制)
原理:当捕捉到信号的跳变沿时,将CNT的值所存到捕获寄存器CCR中,然后把两次的值相减,就可以得到脉宽或者频率。
1499 0
|
数据处理
STM32实现DMA接收串口数据
STM32实现DMA接收串口数据
304 0
|
存储 关系型数据库 编译器
STM32学习笔记:读写内部Flash(介绍+附代码)
STM32学习笔记:读写内部Flash(介绍+附代码)
429 0
|
缓存 Go
STM32使用HAL库实现串口通讯——理论讲解
STM32使用HAL库实现串口通讯——理论讲解
395 0
|
缓存
STM32使用HAL库实现串口通讯——实战操作
STM32使用HAL库实现串口通讯——实战操作
283 0
|
数据格式
【STM32】串口通讯USART串口中断配置
【STM32】串口通讯USART串口中断配置
594 0
STM32CubeMX串口USART中断发送接收数据
上一篇文章 详细介绍了 USART 串口 不使用中断 发送接收数据 ,这篇文章 将介绍如何 使用中断控制 USART 串口 发送接收数据。 对于如何根据 CubeMX 生成 USART 的工程,可以参考我的上篇文章,也介绍了 关于生成 usart.c 代码的解析 : STM32Cube串口USART发送接收数据
373 0
|
芯片
STM32Cube串口USART发送接收数据
这篇文章介绍 实现 USART 异步模式下 通过 串口助手 发送,接收 数据
205 0