STM32
登录
直播中
张燕
7年用户
1339经验值
私信
关注
[问答]
如何利用软件模拟的方法去实现串口收发的功能呢
开启该帖子的消息推送
模拟串口
如何利用软件模拟的方法去实现串口收发的功能呢?串口收发有哪几种通讯方式呢?
回帖
(1)
李慧
2021-12-14 13:52:38
由于项目系统功能版本升级,需要开发一个带有串口收发的功能,但是硬件串口已经全部使用,发现还剩余部分普通gpio口可以使用,故打算采用软件模拟的方法实现该功能;
很久以前使用过51单片机来实现过类似功能,现在首次使用stm32来实现该功能;先借鉴一些网上的demo;
产品的代码初始框架不是我自己搭建的,下回轮到我来搭,一定一定用操作系统来完成,要不然资源的配置,考虑太多,真的麻烦死了;
1.阻塞的通讯
阻塞式通讯
51单片机,是没有操作系统的,并且定时器也是非常的有限的;所以再模拟iic通讯,或者模拟SPI,或者模拟串口uart通讯的时候,通讯是需要delay来延时(delay函数)的位置;延时函数往往是让系统空闲下来等待做不其他事情,很浪费系统的时间资源(这种等待占用了系统时间做“无用之事”,具“阻塞”作用);比如下方这个:使用定时器来计时!
{这个算是稍微高级一点的延迟处理(比单纯的i--好),这个只要将其优先级别放到最低,既可实现不影响中断的处理!}
2 非阻塞式通讯-发送操作
就是我通讯需要的延时不占用系统空闲时间:她需要通讯时,正常通讯,当到达该延时的时刻时,把cpu交给其他任务执行(执行其他任务也需要耗费一些时间的),到继续通讯后,自己得到获取处理权限,继续执行。。。
这是很多操作系统可以完成最基本功能;
由于我的代码框架已经基本固定死了,现在在单片机用基本定时器来完成这样的事情。。。。即完成非阻塞式通讯!
(1)定时器开启如下:
(2)调用发送函数:
UART4_Send_Buf(...);//注意STM32F103C8t6是没有串口4的!!!这是虚拟串口!!
(3)调用的发送函数里面开启了定时器,所以接下来将在定时期中断中进行发送操作
发送函数模拟了串口的时序:开始-发送-结束
发送完一个字节,然后从缓冲区callback(),调用下一个字节进行传输!
代码段如下:
static void send_remain_byte(void)
{
if(VirtualUart.send_cnt>=VirtualUart.send_max)
{
VirtualUart.send_flag=0;//发送完毕
}
else
{
VirtualUart.TXREG=VirtualUart.sendbuff[VirtualUart.send_cnt++];
//Tx_Pin=0; //产生START信号
}
}
/**************************实现函数********************************************
*函数原型:void UART4_Send_Buf(unsigned char *buf,unsigned char len)
*功 能:通过模拟出来的串口-UART4 发送几个字节 的数据
unsigned char *buf 存放数据的数组指针
unsigned char len 要发送的字节数
*******************************************************************************/
void UART4_Send_Buf(unsigned char *buf,unsigned char len)
{
unsigned char i ;
for(i=0;i{
VirtualUart.sendbuff
=*buf;
}
VirtualUart.send_cnt=0;//清除所得的数据大小
VirtualUart.send_max=len;//长度
VirtualUart.send_flag=1;//开始发生
VirtualUart.send_mode=1;//模式为非阻塞方式
TIM4->CR1|=0x01; //使能定时器4
flag_firstBitGet=1;
}
//TIM4定时器里调用
static u8 tim_send_byte(void (*Callback)(void))
{
static int sendidx=0;
if(flag_firstBitGet)
{
flag_firstBitGet=0;
if(Callback!=NULL) //还有数据-->有多个字节要发送,调用回调函数继续发送下一个字节
Callback();
else
VirtualUart.send_flag=0;//没数据了
}
if(sendidx==0)
{
sendidx++;
Tx_Pin=0; //产生START信号
}
elseif(sendidx<=8)//DATA 1,2,3...8
{
sendidx++;
Tx_Pin=VirtualUart.TXREG&0x01;
VirtualUart.TXREG>>=1;
} else if(sendidx==9)
{ //STOP
Tx_Pin=1;
sendidx++;
}
else if(sendidx==10)
{//STOP的发送完毕了
sendidx=0;
if(Callback!=NULL) //还有数据-->有多个字节要发送,调用回调函数继续发送下一个字节
Callback();
else
VirtualUart.send_flag=0;//没数据了
return 0;//返回0-完整的一个字节传输完成
}
return 1;//返回1-正在传输字节过程中-busy
}
//定时器4中断服务程序
void TIM4_IRQHandler(void) //TIM4中断
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //检查TIM4更新中断发生与否
{
tim4Counts++;
TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //清除TIMx更新中断标志
LED1=!LED1;
if(VirtualUart.send_mode) //发送模式:非阻塞
{
if(tim_send_byte(send_remain_byte)==0)//=0说明发送结束
{
if(VirtualUart.send_flag==0)//发送处在结束状态
TIM4->CR1 &= ~TIM_CR1_CEN;//关闭定时器
TIM4->CNT=0;//清除定时器计数的数值
}
}
//else //
//{
//if(tim_send_byte(NULL)==0)
//{
//TIM4->CR1 &= ~TIM_CR1_CEN;//关闭定时器
//TIM4->CNT=0;//清除定时器计数值
//}
//}
}
}
3 非阻塞式通讯-发送操作
这也不难作,来来回回就是有点绕
由于项目系统功能版本升级,需要开发一个带有串口收发的功能,但是硬件串口已经全部使用,发现还剩余部分普通gpio口可以使用,故打算采用软件模拟的方法实现该功能;
很久以前使用过51单片机来实现过类似功能,现在首次使用stm32来实现该功能;先借鉴一些网上的demo;
产品的代码初始框架不是我自己搭建的,下回轮到我来搭,一定一定用操作系统来完成,要不然资源的配置,考虑太多,真的麻烦死了;
1.阻塞的通讯
阻塞式通讯
51单片机,是没有操作系统的,并且定时器也是非常的有限的;所以再模拟iic通讯,或者模拟SPI,或者模拟串口uart通讯的时候,通讯是需要delay来延时(delay函数)的位置;延时函数往往是让系统空闲下来等待做不其他事情,很浪费系统的时间资源(这种等待占用了系统时间做“无用之事”,具“阻塞”作用);比如下方这个:使用定时器来计时!
{这个算是稍微高级一点的延迟处理(比单纯的i--好),这个只要将其优先级别放到最低,既可实现不影响中断的处理!}
2 非阻塞式通讯-发送操作
就是我通讯需要的延时不占用系统空闲时间:她需要通讯时,正常通讯,当到达该延时的时刻时,把cpu交给其他任务执行(执行其他任务也需要耗费一些时间的),到继续通讯后,自己得到获取处理权限,继续执行。。。
这是很多操作系统可以完成最基本功能;
由于我的代码框架已经基本固定死了,现在在单片机用基本定时器来完成这样的事情。。。。即完成非阻塞式通讯!
(1)定时器开启如下:
(2)调用发送函数:
UART4_Send_Buf(...);//注意STM32F103C8t6是没有串口4的!!!这是虚拟串口!!
(3)调用的发送函数里面开启了定时器,所以接下来将在定时期中断中进行发送操作
发送函数模拟了串口的时序:开始-发送-结束
发送完一个字节,然后从缓冲区callback(),调用下一个字节进行传输!
代码段如下:
static void send_remain_byte(void)
{
if(VirtualUart.send_cnt>=VirtualUart.send_max)
{
VirtualUart.send_flag=0;//发送完毕
}
else
{
VirtualUart.TXREG=VirtualUart.sendbuff[VirtualUart.send_cnt++];
//Tx_Pin=0; //产生START信号
}
}
/**************************实现函数********************************************
*函数原型:void UART4_Send_Buf(unsigned char *buf,unsigned char len)
*功 能:通过模拟出来的串口-UART4 发送几个字节 的数据
unsigned char *buf 存放数据的数组指针
unsigned char len 要发送的字节数
*******************************************************************************/
void UART4_Send_Buf(unsigned char *buf,unsigned char len)
{
unsigned char i ;
for(i=0;i{
VirtualUart.sendbuff
=*buf;
}
VirtualUart.send_cnt=0;//清除所得的数据大小
VirtualUart.send_max=len;//长度
VirtualUart.send_flag=1;//开始发生
VirtualUart.send_mode=1;//模式为非阻塞方式
TIM4->CR1|=0x01; //使能定时器4
flag_firstBitGet=1;
}
//TIM4定时器里调用
static u8 tim_send_byte(void (*Callback)(void))
{
static int sendidx=0;
if(flag_firstBitGet)
{
flag_firstBitGet=0;
if(Callback!=NULL) //还有数据-->有多个字节要发送,调用回调函数继续发送下一个字节
Callback();
else
VirtualUart.send_flag=0;//没数据了
}
if(sendidx==0)
{
sendidx++;
Tx_Pin=0; //产生START信号
}
elseif(sendidx<=8)//DATA 1,2,3...8
{
sendidx++;
Tx_Pin=VirtualUart.TXREG&0x01;
VirtualUart.TXREG>>=1;
} else if(sendidx==9)
{ //STOP
Tx_Pin=1;
sendidx++;
}
else if(sendidx==10)
{//STOP的发送完毕了
sendidx=0;
if(Callback!=NULL) //还有数据-->有多个字节要发送,调用回调函数继续发送下一个字节
Callback();
else
VirtualUart.send_flag=0;//没数据了
return 0;//返回0-完整的一个字节传输完成
}
return 1;//返回1-正在传输字节过程中-busy
}
//定时器4中断服务程序
void TIM4_IRQHandler(void) //TIM4中断
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //检查TIM4更新中断发生与否
{
tim4Counts++;
TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //清除TIMx更新中断标志
LED1=!LED1;
if(VirtualUart.send_mode) //发送模式:非阻塞
{
if(tim_send_byte(send_remain_byte)==0)//=0说明发送结束
{
if(VirtualUart.send_flag==0)//发送处在结束状态
TIM4->CR1 &= ~TIM_CR1_CEN;//关闭定时器
TIM4->CNT=0;//清除定时器计数的数值
}
}
//else //
//{
//if(tim_send_byte(NULL)==0)
//{
//TIM4->CR1 &= ~TIM_CR1_CEN;//关闭定时器
//TIM4->CNT=0;//清除定时器计数值
//}
//}
}
}
3 非阻塞式通讯-发送操作
这也不难作,来来回回就是有点绕
举报
更多回帖
rotate(-90deg);
回复
相关问答
模拟串口
如何
去
实现
USB
模拟
串口
收发
的
功能
呢
2021-12-06
1999
怎样使用FIFO
去
实现
串口
数据的
收发
功能
呢
2022-01-27
1053
如何
利用
DMA方式
去
实现
串口
的转发
功能
呢
2022-01-27
1587
STM32
软件
模拟
串口
怎么
去
实现
呢
2022-01-25
722
STM32
软件
模拟
串口
怎么
去
实现
呢
2021-12-07
1509
如何
利用
Python
去
实现
Arduino UNO的
串口
通信
呢
2021-12-21
1340
STM32 IO
模拟
实现
软件
串口
的
方法
2021-12-06
1251
如何
利用
printf函数来
实现
STM32
串口
打印的
功能
呢
2021-12-01
957
如何
去
实现
stm32
串口
usart1的
收发
代码
呢
?
2021-12-09
1460
有什么
方法
能够
实现
UART
串口
打印浮点数
呢
2022-01-19
1135
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
英国威廉希尔公司网站
william hill官网 版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分