发布时间:2020-06-28 阅读量:920 来源: 我爱方案网 作者:
【编者按】有时由于单片机的硬件串口不够用,在要求不高的情况下,比如发送一些调试信息,我们就可以使用I/O口模拟一个串口以完成要做的事情。要自己模拟串口,我们必须要知道串口时序图,如下图所示。
知道时序图,我们就可以编写代码。下面代码是我写的一个模拟串口,波特率取决于你的要求,但模拟串口不宜使用高波特率,一般而言推荐9600以下会比较好,另外该模拟串口没有奇偶校验位。
首先来看看sim_uart.h文件。
//sim_uart.h
#ifndef _SIM_UART_
#define _SIM_UART_
#include "stm8s.h" //替换成自己的头文件
#define SIM_UART_IO_H GPIOA->ODR |= 0x08 //拉高,需要更换成你自己的管脚
#define SIM_UART_IO_L GPIOA->ODR &= ~0x08//拉低,需要更换成你自己的管脚
//把每一个数据按照时序图发送出去。为保证实时性,这个函数需要在中断中调用,调用
//间隔取决于串口波特率。比如我需要的串口波特率是9600bps,那么传送一bit所要的时
//间就是104us,此时中断的调用间隔就是104us
void app_sim_uart_transmit(void );
//把一个字节的数据复制到串口缓冲区,这相当于把数据放到硬件串口的数据缓冲区
void app_sim_uart_tx_set_data(unsigned char data);
//查询一个串口缓冲区的数据是否发送完成,如果完成返回0,否则返回1
unsigned char app_sim_uart_get_tx_state(void );
//初始化模拟串口模块的参数
void app_sim_uart_init(void );
#endif
复制代码
再看看sim_uart.c文件。
//sim_uart.c
#include "sim_uart.h"
struct
{
unsigned char data;
unsigned char step : 3,
start_f : 1,
bit_cnt: 4;
}sim_uart;
typedef enum
{
SIM_UART_IDEL,
SIM_UART_DATA_SEND_START,
SIM_UART_DATA_SEND,
SIM_UART_DATA_SEND_DONE
}sim_uart_send_state_t;
////////////////////////////////////////////////////////////////////////////////
//初始化串口模块
void app_sim_uart_init(void )
{
sim_uart.step = SIM_UART_DATA_SEND_INIT;
sim_uart.start_f = 0;
SIM_UART_IO_H;
}
//检查发送状态
unsigned char app_sim_uart_get_tx_state(void )
{
if(!sim_uart.start_f)
{
return 0;
}
return 1;
}
//将数据放到串口缓冲区
void app_sim_uart_tx_set_data(unsigned char data)
{
sim_uart.data = data;
sim_uart.start_f = 1;
sim_uart.step = SIM_UART_DATA_SEND_INIT;
}
//这个函数模拟了串口的时序
void app_sim_uart_transmit(void )
{
if(sim_uart.start_f == 1)
{
switch(sim_uart.step)
{
case SIM_UART_DATA_SEND:
if(sim_uart.data & 1)
{
SIM_UART_IO_H;
}
else
{
SIM_UART_IO_L;
}
sim_uart.data >>= 1;
if(++sim_uart.bit_cnt >= 8)
{
sim_uart.bit_cnt = 0;
sim_uart.step = SIM_UART_DATA_SEND_DONE;
}
break;
case SIM_UART_DATA_SEND_DONE:
SIM_UART_IO_H;
sim_uart.start_f = 0;
sim_uart.step = SIM_UART_DATA_SEND_INIT;
break;
case SIM_UART_DATA_SEND_START:
SIM_UART_IO_L;
sim_uart.step = SIM_UART_DATA_SEND;
break;
case SIM_UART_DATA_SEND_INIT:
SIM_UART_IO_H;
sim_uart.bit_cnt = 0;
sim_uart.step = SIM_UART_DATA_SEND_START;
break;
}
}
}
复制代码
再看看sim_uart.c文件。
//sim_uart.c
#include "sim_uart.h"
struct
{
unsigned char data;
unsigned char step : 3,
start_f : 1,
bit_cnt: 4;
}sim_uart;
typedef enum
{
SIM_UART_IDEL,
SIM_UART_DATA_SEND_START,
SIM_UART_DATA_SEND,
SIM_UART_DATA_SEND_DONE
}sim_uart_send_state_t;
////////////////////////////////////////////////////////////////////////////////
//初始化串口模块
void app_sim_uart_init(void )
{
sim_uart.step = SIM_UART_DATA_SEND_INIT;
sim_uart.start_f = 0;
SIM_UART_IO_H;
}
//检查发送状态
unsigned char app_sim_uart_get_tx_state(void )
{
if(!sim_uart.start_f)
{
return 0;
}
return 1;
}
//将数据放到串口缓冲区
void app_sim_uart_tx_set_data(unsigned char data)
{
sim_uart.data = data;
sim_uart.start_f = 1;
sim_uart.step = SIM_UART_DATA_SEND_INIT;
}
//这个函数模拟了串口的时序
void app_sim_uart_transmit(void )
{
if(sim_uart.start_f == 1)
{
switch(sim_uart.step)
{
case SIM_UART_DATA_SEND:
if(sim_uart.data & 1)
{
SIM_UART_IO_H;
}
else
{
SIM_UART_IO_L;
}
sim_uart.data >>= 1;
if(++sim_uart.bit_cnt >= 8)
{
sim_uart.bit_cnt = 0;
sim_uart.step = SIM_UART_DATA_SEND_DONE;
}
break;
case SIM_UART_DATA_SEND_DONE:
SIM_UART_IO_H;
sim_uart.start_f = 0;
sim_uart.step = SIM_UART_DATA_SEND_INIT;
break;
case SIM_UART_DATA_SEND_START:
SIM_UART_IO_L;
sim_uart.step = SIM_UART_DATA_SEND;
break;
case SIM_UART_DATA_SEND_INIT:
SIM_UART_IO_H;
sim_uart.bit_cnt = 0;
sim_uart.step = SIM_UART_DATA_SEND_START;
break;
}
}
}
复制代码
最后来看看如何应用上述的模拟串口。
首先,在硬件中断中调用app_sim_uart_transmit()函数,如下所示。
//9600bps,104us定时中断
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
{
app_sim_uart_transmit();
TIM4->SR1 = (uint8_t)(~TIM4_IT_UPDATE);
}
复制代码
接下来我们可以在应用层中使用模拟串口了,如下所示。
#include "sim_uart.h"
main()
{
app_sim_uart_init();
while(1)
{
//检查串口缓冲区是否为空,如果为空,发送下一个字节
if(app_sim_uart_get_tx_state() == 0)
{
//发送下一个字节的数据
app_sim_uart_tx_set_data(0xaa);
}
}
}
复制代码
上述代码是经过实际检验的,如果需要,可以在自己的项目中简单修改一下I/O口后应该就能方便的移植到你的项目中了。
本文作者:会笑的星星是一名设计开发工程师,在平台上的用户名为“ 1585292050XQYe”,有多年的物联网安防产品设计开发经验。
在现代汽车行业中,HUD平视显示系统正日益成为驾驶员的得力助手,为驾驶员提供实时导航、车辆信息和警示等功能,使驾驶更加安全和便捷。在HUD平视显示系统中,高精度的晶振是确保系统稳定运行的关键要素。YSX321SL是一款优质的3225无源晶振,拥有多项卓越特性,使其成为HUD平视显示系统的首选。
随着医疗技术的进步,心电监护设备在日常生活和医疗领域中起到了至关重要的作用。而无源晶振 YSX211SL 作为一种先进的心电贴产品,以其独特的优势在市场上备受瞩目。
对于可编程晶振选型的话,需要根据企业的需求选择。在选择可编程晶振的时候注重晶振外观、晶振的频率、晶振的输出模式、晶振的型号等等,这些都是要注意的,尤其是晶振的频率和晶振输出模式以及晶振的型号都是需要注意的。
在现代科技发展中,服务器扮演着越来越重要的角色,为各种应用提供强大的计算和数据存储能力。而高品质的服务器组件是确保服务器稳定运行的关键。YSO110TR宽电压有源晶振,作为服务器的重要组成部分,具备多项优势,成为业界必备的可靠之选。
其实对于差分晶振怎么测量方式有很多种,主要还是要看自己选择什么样的方式了,因为选择不同的测量方式步骤和操作方式是不同的。关于差分晶振怎么测量的方式,小扬给大家详细的分享一些吧!