模拟串口UART的实现

2023-05-16

我所祷告的,就是要你们的爱心,在知识和见识上,多而又多,使你们能分辨是非,做诚实无过的人,直到基督的日子。
——腓立比书【1:9~10】

最近在调的MCU的型号为STM32F030,配置芯片相较之前的MCU都比较简单,功能配置很顺利。但是在写串口程序的时候,发现串口一直不通,使用示波器也没有波形。因为基本的串口通讯线只有Tx和Rx两根线,配置也相对简单,8位数位,1位停止位,9600波特率。协议结构为 起始位(低电平)+8位数据(低位在前)+1位停止位(高电平),例如发送字节0x55,即电平为低 高低高低高低高低 高。电平转换的间隔时间为1s/9600 = 104us

以上均为理论分析过程,检查代码对串口的配置都没有发现错误。最终排查的结果是硬件工程师画原理图和PCB图时将串口的Tx和Rx画反了!由于某些原因板子已经量产了,故只能通过改软件来实现串口的功能,在网上找了一下发现模拟串口可行性可以,故动手写了一下模拟串口。

串口通讯需要模拟两根线(Tx和Rx)的时序,模拟串口的主要思路如下:

发送部分比较简单,按照 起始位(低电平)+8位数据(低位在前)+1位停止位(高电平),间隔时间104us,即可。

接收部分有点复杂,需要配置一个外部中断,用于检测低电平信号,还需要一个定时器,用于读取有效数据。

下面将代码附上:

发送IO口初始化

/*!
 * @brief 	模拟串口1 TX IO口配置
 * @param	none
 * @return	none
 * @note	Tx(PA10)
 */
void MUSART1_TX_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;		 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure); 
    GPIO_SetBits(GPIOA, GPIO_Pin_10);
}

接收IO口初始化

/*!
 * @brief 	模拟串口1 RX IO口配置
 * @param	none
 * @return	none
 * @note	Rx(PA9)
 */
void MUSART1_RX_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
      
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);    //!<外部中断时钟
	
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;		 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure); 
	
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource9);  
    
    EXTI_InitStructure.EXTI_Line=EXTI_Line9;  
    EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;  
    EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;    //下降沿中断
    EXTI_InitStructure.EXTI_LineCmd=ENABLE;  
    EXTI_Init(&EXTI_InitStructure); 
     
    NVIC_InitStructure.NVIC_IRQChannel=EXTI4_15_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPriority=0x01;  
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;  
    NVIC_Init(&NVIC_InitStructure);
}

定时器初始化

/*!
 * @brief	定时器14初始化 
 * @param
 * @return	NONE
 * @note	103us定时器,用于串口数据采样
 */
void Time14Init(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimerBaseStruct;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);   //!<时钟使能
    TIM_DeInit(TIM14);					    //!<Time1定时器重设缺省值
    TIM_TimerBaseStruct.TIM_Period=103;     		    //!<设置重载寄存器初值 (设置为103,即:定时104us)
    TIM_TimerBaseStruct.TIM_Prescaler=7;     	//!<使用内部8M时钟,分频8(7+1),8M/8 = 1000000,故数1000000(999999+1)下,达1秒
    TIM_TimerBaseStruct.TIM_ClockDivision=0;		    //!<不分频
    TIM_TimerBaseStruct.TIM_CounterMode=TIM_CounterMode_Up; //!<设置计数器向上计数模式
    TIM_TimeBaseInit(TIM14,&TIM_TimerBaseStruct);

    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel=TIM14_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    TIM_ClearITPendingBit(TIM14, TIM_FLAG_Update);
    TIM_ITConfig(TIM14,TIM_IT_Update,ENABLE);  		    //!<使能TIM1中断源
    TIM_Cmd(TIM14,DISABLE);                     	    //!<禁能TIM1定时器	
	
}

发送数据函数

uint32 delayTime =99;	//!<9600,理论值为104但实际测下来99时效果最好
/*!
 * @brief 	模拟串口1发送一个字节
 * @param	
 * @return	none
 * @note	数据低位在前高位在后
 */
void MUSART1_SendData(uint8 data)
{
	uint8 i = 0;
	TX_L();		//!<起始位
	delay_us(delayTime);
	for(i = 0; i < 8; i++){
		if(data & 0x01)
			TX_H();
		else
			TX_L();
		delay_us(delayTime);
		data >>= 1;
	}
	TX_H();		//!<停止位
	delay_us(delayTime);
}

接收数据,外部中断起始接收

/*!
 * @brief	串口接收IO中断处理函数
 * @param	none
 * @return	NONE
 * @note	none
 */
void EXTI4_15_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line9) != RESET){
		if(RX_READ() == 0x00){
			if(rx_state >= STATE_STOP){
				recvData = 0;
				rx_state = STATE_START;
				delay_us(50);
				TIM_Cmd(TIM14, ENABLE);	//!<打开定时器,接收数据
			}
		}
        EXTI_ClearITPendingBit(EXTI_Line9);
    }
}

接收数据,定时器中断接收数据

/*!
 * @brief	定时器1中断处理函数
 * @param
 * @return	NONE
 * @note	 
 */
void TIM14_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM14, TIM_IT_Update) != RESET){
	  	rx_state++;                         //!<改变状态机
		if(rx_state == STATE_STOP){
			TIM_Cmd(TIM14, DISABLE);    //!<关闭定时器
			usart_getByte();            //!<接收到停止位之后,处理数据recvData
			return;                     //!<返回
		}
		if(RX_READ()){
			recvData |= (1 << (rx_state - 1));
		}else{
			recvData &= ~(1 <<(rx_state - 1));
		}
		TIM_ClearITPendingBit(TIM14, TIM_FLAG_Update);
	}
}
其他说明
typedef enum{
	STATE_START=0,
	STATE_BIT0,
	STATE_BIT1,
	STATE_BIT2,
	STATE_BIT3,
	STATE_BIT4,
	STATE_BIT5,
	STATE_BIT6,
	STATE_BIT7,
	STATE_STOP
}RX_STATE;

RX_STATE	rx_state = STATE_STOP;
uint8 recvData=0;    //!<接收的一个字节数据,全局变量

至此,模拟串口的代码及原理均已描述完成。单独的串口通讯并没有问题,但是在实际应用中采取了一种特殊的“总线”形式。


本次写的是从机部分的代码,从机接收数据并没有问题,但是在发送数据时,由于所有的从机Tx都挂载在同一根Tx上,并且从机Tx空闲状态时一直是高电平,导致指定从机的起始信号发不出去。故需要再做以下处理,解决以上问题。

当接收到的数据包中的ID为本从机ID时将Tx拉高,否则拉低,这样能够保证当指定ID的从机发送数据时有且只有一个从机再总线上发送数据(其他从机的Tx主动离线)。

好了就记录这么多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

模拟串口UART的实现 的相关文章

  • TM4C123系列(四)————UART串口通信

    一 实验简介 使用TM4C123的串口通信功能实现单片机与PC端通信 二 UART介绍 TM4C123有八个串口 xff0c 其中UART0已经与USB集成 xff0c UART0建议只用来和PC端通信 xff0c 不要与外界通信 除此之外
  • (十三)STM32——串口通信(UART)

    目录 学习目标 内容 通信方法 并行通信 串行通信 通信方向 通信方式 UART 特点 串口参数 通信流程 寄存器 USART SR USART DR USART BRR 过程 代码 运行结果 运行结果 遇到的问题 总结 学习目标 本节我们
  • UART、IIC、SPI、CAN通信的区别与应用

    文章目录 1 通信的基本知识1 1 数据通信的种类1 1 1 串行通信1 1 2 并行通信1 1 3 总结 1 2 数据通信的传输方向1 2 1 单工1 2 2 半双工1 2 3 全双工1 2 4 总结 1 3 数据通信的方式1 3 1 同
  • Jetson Nano – UART

    There is a UART on the J41 GPIO Header of the NVIDIA Jetson Nano Developer Kit Useful when you need a little bit of extr
  • UART协议

    UART协议 简介 UART是通用异步收发传输器 xff08 Universal Asynchronous Receiver Transmitter xff0c 通常称作UART xff0c 是一种异步收发传输器 是设备间进行异步通信的关键
  • 【verilog】UART串口发送(FPGA)

    简述核心代码仿真测试 简述 串口发送是以一定速率发送单bit数据 xff0c 通常一组数据为10bit 空闲状态为高电平 xff0c 起始位为0 xff0c 中间以低位在前的方式发送8bit数据 xff0c 终止位为1 采用计数器 cnt
  • 串口通信协议---UART

    串口通信的分类 UART属于串行 异步 全双工通信 串行通信与并行通信 根据传输数据的位宽 xff0c 串口通信可分为串行通信与并行通信 xff0c 串行通信是指设备之间通过少量数据信号线 一般是 8 根以下 xff0c 地线以及控制信号线
  • C51_day5:串口通信UART

    3 1 串口基本认知 串行接口简称串口 xff0c 也称串行通信接口或串行通讯接口 xff08 通常指COM接口 xff09 xff0c 是采用串行通信方式的扩展接口 串行接口 xff08 Serial Interface xff09 是指
  • UART,SPI,IIC,RS232通信时序和规则

    一 UART 1 串口通信方式 2 串口通信步骤 注意 xff1a 串口协议规定 xff0c 闲置时必须是高电平 校验位 xff1a 是使用奇偶校验 停止位必须高电平 一个0和多个0区分是靠掐时间 异步通信 xff1a 时钟各不一样 二 I
  • 4.RTT-UART-中断接收及轮询发送

    本期博客开始分享RTT的UART xff0c 利用战舰V3的uart2来输入输出一些字符串 UART xff08 Universal Asynchronous Receiver Transmitter xff09 通用异步收发传输器 xff
  • 嵌入式Linux应用开发笔记:串口

    文章目录 目的 基础说明 开发准备 设备树 应用程序 应用程序与演示 代码 演示 总结 设备树文件 目的 串口 UART 是嵌入式设备中比较常用的功能 这篇文章将记录下应用程序中串口操作相关内容 这篇文章中内容均在下面的开发板上进行测试 新
  • 一起学nRF51xx 6 - uart

    前言 通用异步接收器 发送器提供快速 全双工 内置流量控制的异步串行通信 CTS RTS 在硬件方面支持高达1Mbps波特率 支持奇偶校验和第9位数据生成 用于每个UART接口线的GPIO可从芯片上的GPIO中任选 而且可独立配置 这使得芯
  • mega328p-ADC,PWM,UART驱动

    ADC驱动 函 数 名 Ai Init 函数功能 Ai端口初始化 输入参数 void 输出参数 void 返 回 值 void 参考文档 void 创 件 人 程强刚 创建日期 2016 02 09 修改历史 void Ai Init vo
  • 【UART】Verilog实现UART接收和发送模块

    目录 写在前面 UART 工作原理 UART 接收部分 UART RX 模块图 UART RX 时序图 Verilog 实现 UART RX 模块 UART 发送部分 UART TX 模块图 UART TX 时序图 Verilog 实现 U
  • UART通信原理

    UART 通信格式 串口全称叫做串行接口 通常也叫做 COM 接口 串行接口指的是数据一个一个的顺序传输 通信线路简单 使用两条线即可实现双向通信 一条用于发送 一条用于接收 串口通信距离远 但是速度相对会低 串口是一种很常用的工业接口 I
  • ESP32-C3入门教程 基础篇(三、UART模块 — 与Enocean无线模块串口通信)

    测试第三课 ESP32 C3的串口通信测试 老样子 使用Enocean无线模块和ESP32 C3进行串口通信 目录 前言 1 UART示例测试 1 1 UART 基础测试 1 2 与Enocean无线模块串口通信测试 2 ESP32 C3
  • Verilog功能模块——Uart收发

    摘要 本文分享了一种通用的Uart收发模块 可实现Uart协议所支持的任意波特率 任意位宽数据 5 8 任意校验位 无校验 奇校验 偶校验 1校验 0校验 任意停止位 1 1 5 2 的数据传输 此模块需要搭配FIFO使用 以消除发送端和接
  • 使用HAL库开发STM32:UART基础使用

    文章目录 目的 基础说明与初始化 基础说明 初始化 数据接收和发送 轮询方式 中断方式 DMA方式 其它说明 总结 目的 UART 异步串口 是单片机非常常用的一个功能 一般用作设备或模块间通讯的一种方式 通常所说的232或是485通讯从写
  • 从 Linux 用户空间设置 16550A UART 硬件 FIFO 中断级别

    我目前正在使用 16550 兼容的 UART 并且我希望能够更改 FIFO 中断触发级别 我在高 UART 负载下丢失字节 并且我想降低阈值 这是一个动力不足的嵌入式系统 当然 如果我愿意 我可以在 8250 port c 驱动程序中更改它
  • 如何将 microbit 与 BLE 连接并监听按钮按下事件?

    2021 年 11 月 28 日编辑 如果您需要使用蓝牙低功耗将 microbit 连接到计算机 并在单击按钮时执行操作 直接跳并跟随 ukBaz https stackoverflow com users 7721752 ukbaz的回答

随机推荐

  • PHP中的设计模式及其实际应用浅析

    设计模式在各种语言中都有很重要的应用 xff0c 每种设计模式都有其特有的优点以及使用场景 接下来 xff0c 将从单例模式 工厂模式 组合模式以及策略模式四个模式 xff0c 介绍设计模式及其实际项目中的简单应用 一 单例模式 单例模式的
  • ECMAScript6(6):数组的扩展

    数组的扩展 Array from 将类数组对象和可遍历对象转化为真正的数组 span class hljs keyword var span arrayLike 61 span class hljs string 39 0 39 span
  • 嵌入式stm32f429上成功跑通主流Linux 4.13

    楼主是个闲的蛋疼的大学僧 xff0c 在高中和大学的社团 工作室中长期搞单片机和 嵌入式系统开发 刚接触树莓派时候是惊叹不已的 xff0c 然后眼看香蕉派杨梅派橙子派荔枝派醋鳖派等等等等的 开源硬件 相继登场 xff0c 也是一阵的兴奋 x
  • 【视频】零基础学Android开发:蓝牙聊天室APP(一)

    零基础学Android开发 xff1a 蓝牙聊天室APP第一讲 1 Android介绍与环境搭建 xff1a 史上最高效Android入门学习 1 1 Google的大小战略 1 2 物联网与云计算 1 3 智能XX设备 1 4 Andro
  • 飞行控制器Pixhawk简介

    作者 xff1a 华清远见讲师 Pixhawk是一款由PX4开源项目设计并由3DR公司制造生产的高级自动驾驶仪系统 其前身是APM xff0c 由于APM的处理器已经接近满负荷 xff0c 没有办法满足更复杂的运算处理 xff0c 所以硬件
  • Altium Designer 10 介绍、原理图及其模板常规设计

    作者 xff1a 卢老师 华清远见嵌入式学院讲师 1 Altium Designer 10 入门知识 1 1 1 什么是 Altium Designer Altium Designer 提供了统一的应用方案 xff0c 是 Protel x
  • ubuntu18配置PX4编译环境

    Ubuntu 18 04系统下搭建PX4 Pixhawk原生固件编译环境 经参考总结CSDN上多位开发者的文章 xff0c 经调整亲测可行 xff01 参考文章 xff1a 7条消息 搭建无人机仿真环境之PX4安装中出现的一些问题的解决 T
  • F450机架 Pixhawk飞控实现自动避障(2019.11.29)

    之前进行无人机项目 xff0c 实现避障 巡航 定点 航拍等功能 xff0c 项目结束 xff0c 在这里进行分享经验 xff0c 项目所用器件为自己使用的 xff0c 仅供参考 xff0c 实际实现须结合自己实际情况 1 传感器选择 权盛
  • Java类中final/static修饰的成员变量初始化问题

    文章目录 问题1 final修饰基本数据类型 xff08 final修饰成员变量的初始化方法 xff09 1 代码2 分析 问题2 final修饰静态成员变量的初始化方法1 代码2分析3 问题2 1 问题3 final修饰引用类型的初始化以
  • c++基础知识,有现成的函数不用,非的自己设计算法,这不是坑爹吗?

    那天天气不错 xff0c 小白 xff08 纯属虚构 xff0c 也许是我 xff0c 你猜 xff0c 呵呵 xff09 兴高采烈地去xx手机游戏公司面试 xff0c 带上自己的学历 xff0c 简历 xff0c 还有android 手机
  • 树莓派没有屏幕如何连接WiFi

    Wi Fi 或以太网 如果您想使用本地 lan 的 DHCP 服务器为您的 pi 获取 IP 地址 xff0c 则有两种方法可以将 Pi 连接到互联网 xff1a 首先是使用以太网电缆将 Pi 连接到路由器 在这种情况下 xff0c 您可以
  • 福禄克FLUKE 435-2电能质量分析仪测试瞬态与电压不平衡

    最常影响工业工厂的电功率问题包括电压暂降和暂升 谐波 瞬态 xff0c 以及电压和电流不平衡 在平衡的三相系统中 xff0c 各个相电压应相同或非常接近于相同 不平衡是相电压不相等程度一个度量 电压不平衡是三相系统中各相之间的电压差异指标
  • 在线摄像头

    在线摄像头 2009 07 22 09 49 10人阅读 评论 0 收藏 举报 在Google中输入 inurl 34 ViewerFrame Mode 61 34 或者 inurl 34 MultiCameraFrame Mode 61
  • Docker Desktop的安装

    如果安装了 Docker Desktop xff0c 则已经安装了完整的 Docker xff0c 包括 Compose 一 在 Ubuntu 上安装 Docker Desktop DEB 包 先决条件 要成功安装 Docker Deskt
  • Intel Realsense D435i Firmware Update

    Intel Realsense D435i Firmware Update 0 引言1 更新2 显示设备信息 0 引言 固件下载更新教程 1 更新 固件名称 xff1a Signed Image UVC lt firmware versio
  • Intel RealSense D435i Calibration

    Intel RealSense D435i Calibration 0 引言1 标定工具安装1 1 imu utils Install1 2 kalibr Install 2 IMU标定3 相机标定4 IMU 43 相机联合标定5 VINS
  • G2O优化

    G2O优化 0 引言0 1 参考0 1 G2O的解决问题0 2 G2O整体框架 1 基本使用1 1 构造 g2o 模型1 2 g2o 类图 2 g2o 的顶点 xff08 Vertex xff09 2 1 顶点的格式2 2 自定义顶点2 3
  • Kalman Filter

    Kalman Filter 0 引言1 Kalman Filter1 1 建模1 2 五个重要公式 2 推导3 MatlabDemo 0 引言 卡尔曼滤波 xff08 Kalman filtering xff09 一种利用线性系统状态方程
  • 发一套最完整的直升机原理(绝对完整,绝对精华)

    发一套最完整的直升机原理 xff08 绝对完整 xff0c 绝对精华 xff09 这是找到的最完整 xff0c 最系统介绍直升机的原理及发展史的文章 转到这里 xff0c 送给论坛里喜欢飞行 xff0c 向往蓝天的朋友 xff01 xff0
  • 模拟串口UART的实现

    我所祷告的 xff0c 就是要你们的爱心 xff0c 在知识和见识上 xff0c 多而又多 xff0c 使你们能分辨是非 xff0c 做诚实无过的人 xff0c 直到基督的日子 腓立比书 1 9 10 最近在调的MCU的型号为STM32F0