首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

STM32 普通IO模拟串口UART(含代码示例-已编译验证)

  • 25-04-24 13:04
  • 4681
  • 10582
blog.csdn.net

文章目录

  • 1、为什么要IO模拟串口?
  • 2、原理
    • 2.1 UART 串口协议
    • 2.2 发送/接收一个数据位的延时
    • 2.3 发送原理
      • 2.3.1 发送延时的实现方法
        • 方法1:delay_us()
        • 方法2:定时器
      • 2.3.2 发送流程
    • 2.4 接收原理
      • 2.4.1 外部中断-检测下降沿 + 定时器
  • 3 代码示例
    • 3.1 引脚配置 + 外部中断开启 + 定时器开启
    • 3.2 发送一个字符
    • 3.3 接收定时器中断函数
  • 4 总结
    • 4.1 完整示例代码工程下载地址


1、为什么要IO模拟串口?

  • 开发STM32F103芯片的时候发现串口UART不够用了。临时更换芯片,价格贵而且要更换标准库重新开发也麻烦。

2、原理

2.1 UART 串口协议

  • IO口需要遵循串口协议,下面均以8个数据位,1个停止位,无校验为例
    在这里插入图片描述

2.2 发送/接收一个数据位的延时

  • 计算公式:Delay_Times = 1 / 波特率 * 1000000 us
  • 波特率 = 9600,则 Delay_Times = 1 / 9600 * 1000000 ≈ 104.167 us
  • 波特率 = 115200,则 Delay_Times = 1 / 115200* 1000000 ≈ 8.68. us

2.3 发送原理

2.3.1 发送延时的实现方法

方法1:delay_us()
  • 我用STM32默认的delay_us()也可以正常实现发送,网上有人会说延时不精准,我发现波特率≤9600时发送挺稳定的,但是>9600时,会出现发送的数据乱码。
方法2:定时器
  • 为了更精准的延时,我使用定时器来做延时,波特率115200下,也可以正常发送数据,
  • 所以具体用哪一种方法去实现发送延时,可以根据自己的精度需求去选择

2.3.2 发送流程

  • 根据数据位的值,控制 TXD IO脚高低电平发送一字节(8个数据位),数据位值为 1 则拉高 / 0 则拉低TXD,逐个传输数据位
启动位bit0bit1bit2. . .bit7停止位
拉低TXDDelay 延时拉高/低TXDDelay 延时拉高/低TXDDelay 延时拉高/低TXD. . .Delay 延时拉高/低TXDDelay 延时拉高TXDDelay 延时

2.4 接收原理

2.4.1 外部中断-检测下降沿 + 定时器

  • MCU通过外部中断检测 接收引脚-RXD 的下降沿,检测到下降沿即“启动位”后,打开定时器,每隔“传输1个数据位所需时间”,就会触发一次定时器中断,此时MCU根据接收引脚-RXD的高低电平来确认每个数据位的值并存储起来,直到MCU接收到停止位,关闭定时器,继续检测外部中断的下一个启动位

3 代码示例

  • 文末有完整的代码示例下载地址

3.1 引脚配置 + 外部中断开启 + 定时器开启

void DIDO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
	
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 			// IO口速度为50MHz
  
  	// (TXD)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;			// 推挽输出
	GPIO_Init(GPIOC, &GPIO_InitStructure);						// 推挽输出 ,IO口速度为50MHz
  	GPIO_SetBits(GPIOC, GPIO_Pin_6);                      		// 引脚拉高
	
	// (RXD)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;			    // 上拉输入
	GPIO_Init(GPIOD, &GPIO_InitStructure);								
  
	EXTI15_Init();							// 接收外部中断配置
	TIM4_Init(BuadRate_115200, 71);			// 接收定时器配置
	TIM8_Init(65535 - 1, 71);				// 发送定时器配置
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

3.2 发送一个字符

/*****************  发送一个字符 *******************************/

void IO_MultiUart_SendByte(uint8_t Data)
{
  uint8_t i = 0;

  IO_TXD(0);     // 拉低,开始传输

  TIM8_delayUs(BuadRate_115200);
//  delay_us(BuadRate_9600);

  for(i = 0; i < 8; i++)
  {
    if(Data & 0x01)
        IO_TXD(1);  
    else
        IO_TXD(0);      
    
    TIM8_delayUs(BuadRate_115200);
//    delay_us(BuadRate_9600);
    Data = Data>>1;
  }
  
  IO_TXD(1);     // 拉高,结束传输
  TIM8_delayUs(BuadRate_115200);
//  delay_us(BuadRate_9600);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

3.3 接收定时器中断函数

void TIM4_IRQHandler(void)
{  
  if(TIM_GetFlagStatus(TIM4, TIM_FLAG_Update) != RESET)
  {
    TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);   
    RecvStat++;
    
    // 停止位
    if(RecvStat == COM_STOP_BIT)
    {
      TIM_Cmd(TIM4, DISABLE);           // 关闭定时器TIM4
      RecvBuf[RecvIndex++] = RecvData;  // 存储接收到的一个字节  
      return;
    }
    // 非停止位,高/低电平传输数据
    if(IO_RXD)
    {
      RecvData |= (1 << (RecvStat - 1));
    }else{
      RecvData &= ~(1 << (RecvStat - 1));
    }   
  }     
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

4 总结

4.1 完整示例代码工程下载地址

  • 点击下载-STM32 普通IO模拟串口UART(完整代码-已编译验证)

  • 欢迎纠正,(づ ̄3 ̄)づ╭❤~
    如果有帮助到你,能点个赞吗?ღ( ´・ᴗ・` ) 比心

注:本文转载自blog.csdn.net的努力的小肥丸的文章"https://blog.csdn.net/wenjie2017/article/details/145712718"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

124
嵌入式
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top