欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 单片机IO口模拟串口实现原理

单片机IO口模拟串口实现原理

2024/11/30 12:52:13 来源:https://blog.csdn.net/m0_46152793/article/details/139930258  浏览:    关键词:单片机IO口模拟串口实现原理

参考链接

1、使用GPIO来模拟UART
2、STM32之IO模拟串口篇

1、工作原理

单片机IO口模拟串口的实现原理通常是通过软件来模拟串行通信的传输和接收。下面说明了单片机IO口模拟串口的实现原理:

  1. 配置IO口:选择两个IO口作为模拟串口的发送和接收引脚。通常使用的是GPIO引脚。

  2. 设置通信参数:设置波特率、数据位、停止位和校验位等串口通信参数。

  3. 发送数据:通过控制发送引脚的电平变化来模拟串口数据的传输。根据通信参数,将要发送的数据进行位的切换操作,逐位通过发送引脚发送出去。

  4. 接收数据:通过读取接收引脚的电平变化来模拟串口数据的接收。根据通信参数,读取接收引脚的电平状态,逐位组装接收到的数据。

  5. 确保同步:为了确保发送和接收的同步性,可以在发送和接收的开头和结尾添加起始位和停止位。发送时在数据的起始位置输出一个低电平的起始位,接收时检测到低电平的起始位后开始接收数据,接收完毕后检测到高电平的停止位表示接收完成。

单片机IO口模拟串口的实现原理相对简单,但通信速率可能受到单片机性能和IO口速度的限制,因此在高速通信或实时性要求较高的场景下,可能需要选择硬件串口或其他更高级的通信方式。

2、UART协议:

空闲位:当uart处于空闲状态(线路没有数据传输)时,TX、RX线都处于高电平状态(逻辑“1”),一般需要把相应IO口配置为上拉。

起始位:由高电平跳变为低电平,且持续一个位宽度,表示触发起始信号。

数据位:数据位可以5、6、7或8位,从最低位开始一位接着一位的传送。

校验位:有奇、偶或无校验。

	 奇校验:数据位+校验位的“1”的位数总和为奇数;偶校验:数据位+校验位的“1”的位数总和为偶数;

例如:奇校验中,数据位“1”的位数为偶数个,则此时校验位为“1”。

无校验:顾名思义就是没有校验位,数据位后面接停止位。(通常配置为无校验。)

停止位:将数据线拉为高电平,可以设置停止位宽度为1位、1.5位或者2位。

波特率:在串口中波特率为每秒传送的bit数;通信双方必须设置相同的波特率,否则接收的数据为乱码。波特率9600时,传输1bit所需时间为(1/9600)us,大约为104us。

3、代码实现(无OS)

/***/#include "./BSP/MYPRINTF/myprintf.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "./BSP/TIMER/btim.h"//开始接收数据标志
volatile unsigned char uartStartFlag = 0;//串口接收缓存
unsigned char uartBuf[256] = {0};
unsigned char uartBufLen = 0;
unsigned char uartHaveDat = 0;//超时错误处理
volatile unsigned int uartBufTimeout = 0;
volatile unsigned int uartBufStartTimeout = 0;void myuart_init(void)
{GPIO_InitTypeDef gpio_init_struct;TX_GPIO_CLK_ENABLE();gpio_init_struct.Pin = TX_GPIO_PIN;                   gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;         HAL_GPIO_Init(TX_GPIO_PORT, &gpio_init_struct);       RX_GPIO_CLK_ENABLE(); gpio_init_struct.Pin = RX_GPIO_PIN;   gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */   gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;                  HAL_GPIO_Init(RX_GPIO_PORT, &gpio_init_struct);                        HAL_NVIC_EnableIRQ(RX_INT_IRQn);Set_TX(0);                                               
}void send_byte(uint8_t data){Set_TX(0);delay_us(104);for(int i = 0; i < 8; i++){if(data & 0x01){Set_TX(1);}else{Set_TX(0);}delay_us(104);data = data >> 1;}Set_TX(1);delay_us(104);}void send_str(char *dat){for(int i = 0; i < strlen(dat); i++){send_byte(dat[i]);}
}void myprintf(char *fmt, ...){va_list ap;char string[512];va_start(ap, fmt);vsprintf(string, fmt, ap);send_str(string);va_end(ap);
}void RX_INT_IRQHandler(void){HAL_GPIO_EXTI_IRQHandler(RX_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY0所在中断线 的中断标志位 */__HAL_GPIO_EXTI_CLEAR_IT(RX_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){if(GPIO_Pin == RX_GPIO_PIN){if(uartStartFlag == 0){uartStartFlag = 1;btim_timx_int_init(52 - 1, 72 - 1, BTIM_TIM6_INT);    //52us接收数据}}    
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com