UART(串口)

UART协议帧

  在 UART中,传输模式为数据包形式。数据包由起始位、数据帧、奇偶校验位和停止位组成。

  数据帧

起始位

  当不传输数据时, UART 数据传输线通常保持高电压电平。若要开始数据传输,发送UART 会将传输线从高电平拉到低电平并保持1 个时钟周期。当接收 UART 检测到高到低电压跃迁时,便开始以波特率对应的频率读取数据帧中的位。

  起始位

数据位

  数据帧包含所传输的实际数据。如果使用奇偶校验位,数据帧长度可以是5 位到 8 位。如果不使用奇偶校验位,数据帧长度可以是9 位。在大多数情况下,数据以最低有效位优先方式发送。

  数据位

奇偶校验位

  校验位可以配置成 1 位偶校验或 1 位奇校验或无校验位。接收UART 读取数据帧后,将统计数值为 1 的位,检查总数是偶数还是奇数。如果奇偶校验位为0 (偶数奇偶校验),则数据帧中的1或逻辑高位总计应为偶数。如果奇偶校验位为 1 (奇数奇偶校验),则数据帧中的1 或逻辑高位总计应为奇数。当奇偶校验位与数据匹配时,UART 认为传输未出错。但是,如果奇偶校验位为0 ,而总和为奇数,或者奇偶校验位为 1 ,而总和为偶数,则UART 认为数据帧中的位已改变

  校验位

停止位

  为了表示数据包结束,发送 UART 将数据传输线从低电压驱动到高电压并保持1到2位时间。

  停止位

串口工作过程

  1. 当串口信号处于空闲位时,不需要发送数据,串口一直处于高电平状态
  2. 当需要发送数据时,将串口电平拉低一位,此时串口处于起始位,表示需要发送数据
  3. 发送完8位数据后(可以选择无校验),接着有一位停止位将电平拉高表示发送结束,再留一个空闲位,空闲位过后发送下一个数据帧
  4. 所以串口发送数据的效率只有80%

串口配置 

 //在使用串口通信之前需要先配置串口,在使用串口同时也要使用引脚,所以也要配置端口工作模式,需要使用引脚时配置引脚工作模式永远排在第一位
//配置GPIO端口工作模式函数
void GPIO_Config(){
    GPIO_InitTypeDef init;
    init.Mode = GPIO_PullUp;
    init.Pin = GPIO_Pin_0 | GPIO_Pin_0;//我们使用的引脚是P30和P31
    GPIO_Inilize(GPIO_P3,&init);//我们使用的端口是第3组
}
//串口配置函数
void UART_Config(){
    COMx_InitDefine init;
    init.UART_Mode = UART_8bit_BRTx;//传输模式配置
    init.UART_BRT_Use = BRT_Timer1;//波特率发生器
    init.UART_BaudRate = 115200;//波特率配置
    init.UART_RxEnable = ENABLE;//允许接收
    init.Morecommunicate = DISABLE;//多机通讯允许, ENABLE,DISABLE
    init.BaudRateDouble = DISABLE;//波特率加倍
    UART_Configuration(UART1,&init);//这里的UART1是指支持UART协议的端口分组
    NVIC_UART1_Init(ENABLE,Priority_1);//配置UART1的中断使能,配置中断优先级
    UART1_SW(UART1_SW_P30_P31);//引脚切换配置
}
void main(){
    GPIO_Config();
    UART_Config();
    //打开全局中断开关
    EA = 1;
    TX1_write2buff(97);//MCU使用串口1发送97给PC,对应字符a
    while(1);
}
//现在已经配置好了串口,PC和单片机已经可以互相发送数据了,但是由于单片机不能像PC一样给用户一个直观的反馈所以我们需要通过串口通信将PC发送给单片机的数据发送回电脑,来验证能互相通信
//需要在while循环内加上以下代码
//单片机每个串口都有数据寄存器SBUF和存放数据的数组RX1_Buffer[128],当PC发送数据过来时,串口会用SBUF将数据移动到数组中,所以检验PC发送个单片机数据有没有成功,就看数组中有没有发送的数据即可
if(COM1.RX_Cnt > 0 && --COM1.RX_TimeOut == 0){
    //COM1.RX_Cnt是单片机中存放数据的数组的已经存放的长度标志,COM1.RX_TimeOut是一个计数功能,能够保证发送数据的连续性
    for(i = 0;i < COM1.RX_Cnt;i++){
        //遍历单片机中存放数据的数组,通过串口1发送回给PC
		TX1_write2buff(RX1_Buffer[i]);
	}
	COM1.RX_Cnt = 0;
    //取完数据之后将数组中长度标志置零,如果不置零,下次PC发送过来的数据就会继续往后存
}

多机通信

多机通信

//PC1,PC2
void main(){
	int i = 0;
	GPIO_Config();
	UART_Config();
	EA = 1;
	while(1){
		if(COM1.RX_Cnt > 0 && --COM1.RX_TimeOut == 0){
			for(i = 0;i < COM1.RX_Cnt;i++){
				TX4_write2buff(RX1_Buffer[i]);
                //使用串口4将串口1的数组里面的数据拷贝到串口4的数组中
                TX1_write2buff(RX4_Buffer[i]);
                //输出串口4数组中的数据,可以随时打印对方PC发送给单片机的数据
			}
			COM1.RX_Cnt = 0;
		}
		delay_ms(20);
	}
}
void GPIO_Config(){
	GPIO_InitTypeDef init;
	init.Mode = GPIO_PullUp;
	init.Pin = GPIO_Pin_0 | GPIO_Pin_1;
	GPIO_Inilize(GPIO_P3,&init);
        init.Pin = GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_Inilize(GPIO_P5,&init);
}
void UART_Config(){
	COMx_InitDefine init; 
	init.UART_Mode = UART_8bit_BRTx;
	init.UART_BRT_Use = BRT_Timer1;
	init.UART_BaudRate = 115200;
	init.Morecommunicate = ENABLE;
	init.UART_RxEnable = ENABLE;
	init.BaudRateDouble = DISABLE;
	UART1_SW(UART1_SW_P30_P31);
	NVIC_UART1_Init(ENABLE,Priority_0);
	UART_Configuration(UART1,&init);
	init.UART_BRT_Use = BRT_Timer2;
	NVIC_UART2_Init(ENABLE,Priority_0);
	UART_Configuration(UART4,&init);
}

 

 

posted @   剑客温华  阅读(125)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
点击右上角即可分享
微信分享提示