当我从微控制器向桌面发送内容并且桌面上的程序然后将某些内容发送回微控制器时,通信正常.
但是,当我要求将信息从控制器连续发送到桌面程序,直到桌面程序发送特定答案时,它不起作用.
这是我正在谈论的代码:
unsigned char ans = 'N'; unsigned int count = 0; void main(void) { while(1) { if(count == 0) { Configure(); count = 1; } //there is some more code here but is irrelevant to the serial communication } } void Configure() { //Repeat this until the user accepts the sent string as correct while(ans == 'N') { BuildString(); Send(); Receive(); } } void Send() { unsigned int i; TMOD = 0x20; TH1 = 0xFD; SCON = 0x50; TR1 = 1; for(i=0; i<4; i++) { SBUF = toSend[i]; while(TI == 0); TI = 0; } } void Receive() { unsigned int j; TMOD = 0x20; TH1 = 0xFD; SCON = 0x50; TR1 = 1; for(j=0; j<2; j++) { while(RI == 0); Received[j] = SBUF; RI = 0; } if(count == 0) ans = Received[1]; else { RunType = Received[0]; Move = Received[1]; } }
BuildString()函数只是根据一些传感器输入构造一个字符串.
发送和接收功能通常很好,但是当我需要它们连续发送和接收时,就像上面的Configure()函数一样,它不起作用.
有什么建议?我真的很感激他们.
问题是您的发送和接收功能都被轮询和阻止.当您调用receive函数时,它只会在收到完整的消息后返回. Dito用于发送功能,但是在发送的情况下,持续时间可能更短(您的程序将仅在有消息要发送时调用发送,而接收可以在消息到达之前等待几天.如果需要异步通信,最好使用基于中断的通信;至少对于接收和理想的发送和接收.
也可以使用轮询通信来强制执行此操作,但是您需要编写一个函数来检查字符是否可用于接收(或者如果tx-empty),从缓冲区读取/写入下一个字符.
基于中断的通信的优点是:
>全双工
>使用更少的CPU时间(不需要等待循环)
>更少的功率(它允许cpu进入低功耗/待机模式,中断唤醒;轮询总是需要全功率)
作为第一步,我建议您实现(或获得)基于中断的接收;即使发送功能仍然被阻止,它也可以轻松实现全双工操作.如果你没有os(rtos / scheduler),你将不得不考虑同步机制.最简单的形式是,如果有可用消息,您的接收处理消息,如果没有(完整)消息则立即返回.
祝好运.
评论后编辑
在逐个消息的基础上,如果桌面对控制器发送的消息作出反应,事情似乎可行.如果您的控制器在接收上有一个大的FIFO缓冲区(即64字节),这可能会起作用.我知道的大多数控制器都没有这个.许多人只有一个字符缓冲区.您可以使用寄存器中的OVERFLOW位检测到这一点;如果设置了这个,则接收时字符丢失.
一些用例:
*你想一次发送2条消息(比如:init do_something).电脑响应第一个消息,但控制器仍在发送和丢弃大部分数据.
* PC在控制器执行receive()函数之前开始发送.数据包开头的数据可能会丢失
*任何通信中断都可能导致死锁(即控制器和桌面都在等待另一端发送内容.
所以要诊断:检查溢出位.如果已设置,则表示您丢失了数据,并且需要处理中断函数.如果可能的话,监视两侧(至少是状态;闪烁一个led发送,一个用于接收).
一个rs232监视器可以帮助你(你需要一些额外的端口.有很多(包括免费软件)应用程序可以监视多个rs232端口并提供时间戳.所以你可以观察通信的顺序.谷歌找到我:link;在过去的几年里,我使用了几种类似的工具.