串口介绍和串口通信实现
目录
关于电器标准和协议
RS-232
RS-422
RS-485
关于串口的电平
RS232电平
TTL电平
串口接线方式
相关寄存器的配置以及串口的工作模式
stm32HAL库常用函数介绍
串口发送和接收函数
串口中断回调函数
状态标记变量:USART_RX_STA
串口接收中断流程
串口实验(非中断)
编程实现
串口实验(中断)
编程实现
串口基本认知
特点:是设备间接线通信的一种方式数据一位一位地顺序传送双向通信,全双工传送速度相对较慢
关于电器标准和协议
RS-232
RS-422
由于接收器采用高输入阻抗和发送驱动器比RS232更强的驱动能力,故允许在相同传输线上连接多个接 收节点,最多可接10个节点。即一个主设备(Master),其余为从设备(Slave),从设备之间不能通 信,所以RS-422支持点对多的双向通信。 RS-422的最大传输距离为1219米,最大传输速率为10Mb/s。平衡双绞线的长度与传输速率成反比。
RS-485
是从RS-422基础上发展而来的,无论四线还是二线连接方式总线上可多接到32个设备。
关于串口的电平
异步串行是指UART(Universal Asynchronous Receiver/Transmitter),通用异步接收/发送。UART包含TTL电平的串口和RS232电平的串口
RS232电平
TTL电平
串口接线方式
RXD:数据输入引脚,数据接受
TXD:数据发送引脚,数据发送
相关寄存器的配置以及串口的工作模式
字符 'a' 是如何从单片机上传到PC的?
a 的 ASSII 码是 97 , 16 进制就是 0x61, 二进制是 01010001 ,这个 8 位就是 数据位串口工作模式1, 一帧数据有 10 位, 起始位0+数据位+停止位1那么a 的一帧数据就是 0 1000 1010 1
一个字节有8位,比如字母‘a’的ASSII码是十进制97,二进制是 0110 0001 ,一次从地位到高位发送,接收也是
stm32HAL库常用函数介绍
串口发送和接收函数
HAL_UART_Transmit();//串口发送数据,使用超时管理机制
HAL_UART_Receive();//串口接收数据,使用超时管理机制
HAL_UART_Transmit_IT();//串口中断模式发送数据
HAL_UART_Receive_IT();//串口中断模式接收数据
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart,
uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart,
uint8_t *pData, uint16_t Size)
串口中断回调函数
状态标记变量:USART_RX_STA
串口接收中断流程
串口实验(非中断)
4. 使用MicroLIB库
编程实现
# include <stdio.h># include <string.h>unsigned char ch [ 20 ] = { 0 };int fputc ( int ch , FILE * f ){unsigned char temp [ 1 ] = { ch };HAL_UART_Transmit ( & huart1 , temp , 1 , 0xffff );return ch ;}main 函数里:unsigned char ch [ 20 ] = { 0 };HAL_UART_Transmit ( & huart1 , "hello world\n" , strlen ( "hello world\n" ), 100 );while ( 1 ){HAL_UART_Receive ( & huart1 , ch , 19 , 100 );//HAL_UART_Transmit(&huart1, ch, strlen(ch), 100);printf ( ch );memset ( ch , 0 , strlen ( ch ));}
串口实验(中断)
前4步同上
编程实现
# include <stdio.h>// 串口接收缓存( 1 字节)uint8_t buf = 0 ;// 定义最大接收字节数 200( 可根据需求调整)# define UART1_REC_LEN 200// 接收缓冲 , 串口接收到的数据放在这个数组里,最大 UART1_REC_LEN 个字节uint8_t UART1_RX_Buffer [ UART1_REC_LEN ];// 接收状态// bit15 , 接收完成标志// bit14 , 接收到 0x0d// bit13~0 , 接收到的有效字节数目uint16_t UART1_RX_STA = 0 ;// 接收完成回调函数,收到一个数据后,在这里处理void HAL_UART_RxCpltCallback ( UART_HandleTypeDef * huart ){// 判断中断是由哪个串口触发的 所有触发都调用此函数if ( huart -> Instance == USART1 ){// 判断接收是否完成(UART1_RX_STA bit15 位是否为 1 )if (( UART1_RX_STA & 0x8000 ) == 0 ){// 如果已经收到了 0x0d (回车),if ( UART1_RX_STA & 0x4000 ){//则接着判断是否收到 0x0a (换行)if ( buf == 0x0a )//如果 0x0a 和 0x0d 都收到,则将 bit15 位置为 1UART1_RX_STA |= 0x8000 ;else// 否则认为接收错误,重新开始UART1_RX_STA = 0 ;}else // 如果没有收到了 0x0d (回车){//则先判断收到的这个字符是否是 0x0d (回车)if ( buf == 0x0d ){//是的话则将 bit14 位置为1UART1_RX_STA |= 0x4000 ;}else{// 否则将接收到的数据保存在缓存数组里UART1_RX_Buffer [ UART1_RX_STA & 0X3FFF ] = buf ;UART1_RX_STA ++ ; // 如果接收数据大于 UART1_REC_LEN ( 200 字节),则重新开始接收if ( UART1_RX_STA > UART1_REC_LEN - 1 )UART1_RX_STA = 0 ;}}}// 重新开启中断HAL_UART_Receive_IT ( & huart1 , & buf , 1 );}}int fputc ( int ch , FILE * f ){unsigned char temp [ 1 ] = { ch };HAL_UART_Transmit ( & huart1 , temp , 1 , 0xffff );return ch ;}main 函数部分HAL_UART_Receive_IT ( & huart1 , & buf , 1 );while ( 1 ){/* USER CODE END WHILE *//* USER CODE BEGIN 3 *///判断判断串口是否接收完成if ( UART1_RX_STA & 0x8000 ){printf ( " 收到数据: " );// 将收到的数据发送到串口HAL_UART_Transmit ( & huart1 , UART1_RX_Buffer , UART1_RX_STA & 0x3fff , 0xffff );// 等待发送完成while ( huart1 . gState != HAL_UART_STATE_READY );printf ( "\r\n" );// 重新开始下一次接收UART1_RX_STA = 0 ;}printf ( "hello liangxu\r\n" );HAL_Delay ( 1000 );}
好家伙VCC: 博主写的真棒!我最近也写关于STM32智能小车 PID 控制 遥控 避障 跟随循迹的文章和视频,大家可以一起交流学习一下,这是文章:https://blog.csdn.net/qq_46187594/article/details/138110155?spm=1001.2014.3001.5502
好家伙VCC: 博主写的真棒!我最近也写关于STM32智能小车 PID 控制 遥控 避障 跟随循迹的文章和视频,大家可以一起交流学习一下,这是文章:https://blog.csdn.net/qq_46187594/article/details/138110155?spm=1001.2014.3001.5502
alliiin: 什么现象?能运行就行
alliiin: 用面包板
普通网友: 优质好文,支持支持。【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】