赞
踩
1.UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是一种双向、串行、异步的通信总线,仅用一根数据接收线和一根数据发送线就能实现全双工通信。典型的串口通信使用3根线完成,分别是:发送线(TX)、接收线(RX)和地线(GND),通信时必须将双方的TX和RX交叉连接并且GND相连(共用同一个地)才可正常通信,如下图所示:
这里简单介绍一下UART使用的串行通信方式:两个MCU互相收发数据常见的通信方式主要有串行通信和并行通信两种方式!
假设我们要发送198给另一台MCU,首先需要将198转换成机器能够识别的二进制也就是11000110
1.此时使用串行通信方式,我们只需要使用一根线交叉连接两个MCU的Tx-Rx,再使用一根线进行共地,我们就可以依次将八位数据发送给另一台MCU。
2.若使用并行通信,则需要八根线分别发送八位数据,并且为了保证数据的同步性,还需要另外接一根时钟信号线!虽然发送速率较快,但线路成本较高且抗干扰能力较弱。
1.三要素:波特率、数据长度、开始/停止位
要想使用UART收发数据,必须设置好这三个基础设置。
2.数据发送过程
设置好三要素后,我们就可以进行简单的数据发送。下面简单介绍一下发送过程中三要素的作用:
(1)波特率:不同的波特率代表着我们发送数据的速度不同,数据的收发需要波特率的同步,也就是两端的波特率要设置成相同数值。(通常使用较多的设备波特率为9600、115200等)
这里我们假设波特率为9600,也就是说设备每秒发送9600位,一个数据位就需要104微秒;
(2)数据长度:数据帧包含所传输的实际数据。如果使用奇偶校验位,数据帧长度可以是5 位到 8 位。如果不使用奇偶校验位,数据帧长度可以是9 位。在大多数情况下,数据以最低有效位优先方式发送
(3)开始/停止位:开始位以下降沿为标志,也就是从高电平转变到低电平;当不传输数据时, UART 数据传输线通常保持高电压电平。若要开始数据传输,发送UART 会将传输线从高电平拉到低电平并保持1 个时钟周期。当接收 UART 检测到高到低电压跃迁时,便开始以波特率对应的频率读取数据帧中的位。停止位以上升沿为标志,也就是从低电平转变到高电平;为了表示数据包结束,发送 UART 将数据传输线从低电压驱动到高电压并保持1 到 2 位时间。
上图的52us是指,通常在收发数据时,我们会在检测到开始位后等待52us,避免数据的不稳定性。
3.额外说一下奇偶校验位:奇偶性描述数字是偶数还是奇数。通过奇偶校验位,接收 UART判断传输期间是否有数据发生改变。电磁辐射、不一致的波特率或长距离数据传输都可能改变数据位。
校验位可以配置成 1 位偶校验或 1 位奇校验或无校验位。
接收UART 读取数据帧后,将统计数值为 1 的位,检查总数是偶数还是奇数。如果奇偶校验位为0 (偶数奇偶校验),则数据帧中的1或逻辑高位总计应为偶数。如果奇偶校验位为 1 (奇数奇偶校验),则数据帧中的1 或逻辑高位总计应为奇数。
当奇偶校验位与数据匹配时,UART 认为传输未出错。但是,如果奇偶校验位为0 ,而总和为奇数,或者奇偶校验位为 1 ,而总和为偶数,则UART 认为数据帧中的位已改变。
1.接线:
任何 UART 双向通信至少需要 3 个引脚,数据发送引脚 TXD,数据接收引脚 RXD,数 据参考地 GND。这里特别需要注意的是连接方法,设备 A 和设备 B 信号需要交叉连接。如 果电平不同,需要电平转换芯片。
串口1的初始化:引脚为PA9\PA10;
- void Init_Uart1(uint32_t baud) //baud为波特率
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- #if EN_USART1_RX //如果使能了接收
- NVIC_InitTypeDef NVIC_InitStructure;
- #endif
- /* 串口 1 TX = PA9 RX = PA10 */
- /* 第 1 步: 配置 GPIO */
- /* 打开 GPIO 时钟 */
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- /* 打开 UART 时钟 */
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
- /* 配置 USART Tx 为复用功能 */ //USART1_TX GPIOA.9
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
- GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.9
-
- /* 配置 USART Rx 为复用功能 */ //USART1_RX GPIOA.10 初始化
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA10
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
- GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.10
- /* 第 2 步: 配置串口硬件参数 */
- USART_InitStructure.USART_BaudRate = baud; /* 波特率 */
- USART_InitStructure.USART_WordLength = USART_WordLength_8b; /* 字长为 8 位数据格式 */
- USART_InitStructure.USART_StopBits = USART_StopBits_1; /* 一个停止位 */
- USART_InitStructure.USART_Parity = USART_Parity_No; /* 无奇偶校验位 */
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; /* 无硬件数据流控制 */
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; /* 收发模式 */
- USART_Init(USART1, &USART_InitStructure); /* 初始化串口 1 */
- #if EN_USART1_RX //如果使能了接收
- /* 第 3 步: Usart1 NVIC 配置 */
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级 3
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化 VIC 寄存器
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* 开启串口接受中断 */
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); /* 开启串口空闲中断 */
- #endif
- /* 第 4 步: 使能串口 1 */
- USART_Cmd(USART1, ENABLE); /* 使能串口 */
- }
中断服务函数:
- void USART1_IRQHandler(void) //串口 1 中断服务程序
- {
- uint8_t Res=Res;
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到一个字节数据)
- {
- USART_RX_BUF[RxCounter++]=USART1->DR;//把接收到的字节保存
- }
- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //接收中断(接收到 1 帧数据)
- {
- Res=USART1->SR;//读 SR 寄存器
- Res=USART1->DR;//读 DR 寄存器(先读 SR,再读 DR,就是为了清除 IDLE 中断)
- ReceiveState=1;//标记接收状态置位
- }
- }
状态清零函数:
- void Uart0_STA_Clr(void)
- {
- RxCounter = 0;//串口 BUF 计数清零
- ReceiveState = 0;//接收状态清零
- }
为使用printf()打印的重定向函数:(记得包含stdio.h头文件)
- int fputc(int ch, FILE *f)
- {
- while((USART1->SR&0X40)==0){};//;//循环发送,直到发送完毕
- USART1->DR = (u8) ch;
- return ch;
- }
数据发送函数:(16进制)
- void USART1_Send_Data(uint8_t *buf,uint8_t len)
- {
- uint8_t t;
- for(t=0;t<len;t++) //循环发送数据
- {
- while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
- USART_SendData(USART1,buf[t]);
- }
- while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
- }
下图为常用串口助手的设置界面⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇
有需要源代码的朋友可以私,自己学习笔记记录,有错误欢迎大家指正!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。