所有关于电路

为每个字节UART通信ACK /纳

鲁卡

线程启动

鲁卡

加入1月25日,2018年
12
的想法:我想建立公司发射机和接收机之间的通信;公司的一些基本的错误处理。我想实现ACK(确认)/纳(negative-acknowledgement)的错误处理方式。我目前只传输数据从一个设备(PIC18F46K80)和接收它与另一个(PIC18F452)发射机(T)发送“有用的”数据和接收方(右)接受数据和发送回发射机应答或纳克每字节的数据发送。

设置:因为有点复杂,我做了流程图为每个发射机和接收机(只有代码的主要方面考虑)。

发射机和接收机Flowchart-min-min.jpg

这是代码发射机(PIC18F46K80)。代码接收方并不相同,但类似于这一个。我也使用LED显示程序执行的当前位置(例如,当程序遍历“错误”路径或者当遍历“正常运行”路径)和接收的数据解释(LED条形图并行连接PORTD)但这是不包括在这里(改善代码的可读性):

C:
# include < xc。h > # include < stdint。h > # include < stdbool。h > # include " config_bits。h”空白osc_initialize(无效);空白uart_initialize(无效);空白uart_receive (uint8_t * c);空白uart_transmit (uint8_t * c);空白__interrupt () high_isr(无效);uint8_t data_rec; // received data storage variable uint8_t isr_flag = 0; // used to indicate completion of ISR uint8_t ack = 0x06; // acknowledgement code uint8_t nack = 0x15; // negative acknowledgement code // INTIALIZE INTERNAL OSCILLATOR REGISTERS void osc_initialize(void){ OSCCONbits.SCS = 0b10; // set internal oscillator block OSCCONbits.IRCF = 0b101; // set clock frequency to 4MHz while(OSCCONbits.HFIOFS == 0); // wait for oscillator frequency to stabilize } // INITIALIZE UART REGISTERS void uart_initialize(void){ // RX and TX inputs port initialization TRISDbits.TRISD6 = 1; TRISDbits.TRISD7 = 1; SPBRG2 = 25; // SPBRG = ((F_osc/BaudRate)/64)-1 => at F_osc = 4MHz, BaudRate = 2400, low speed TXSTA2bits.BRGH = 0; // 8-bit data mode setting for transmitter/receiver TXSTA2bits.SYNC = 0; // asynchronous mode RCSTA2bits.SPEN = 1; // RX and TX set as serial port pins TXSTA2bits.TXEN = 1; // transmitter enable RCSTA2bits.CREN = 1; // receiver enable INTCONbits.GIEH = 1; // must be set for HP interrupt to be generated INTCONbits.GIEL = 1; // must be set for LP interrupt to be generated PIE3bits.RC2IE = 1; // enable USART receive interrupt } // UART TRANSMISSION FUNCTION void uart_transmit(uint8_t *tran){ do{ TXREG2 = *tran; // load the value of "tran" into TXREG (data stored into TXREG, then send into TSR) while(TXSTAbits.TRMT == 0); // wait for data to be loaded into TSR and send while(isr_flag == 0); // loop is terminated after ISR isr_flag = 0; // reset "isr_flag" } while(data_rec != ack); // got NACK (or anything else) -> re-transmit current data } // UART RECEPTION FUNCTION void uart_receive(uint8_t *rec){ // MAIN ERROR - overrun if(RCSTA2bits.OERR){ RCSTA2bits.CREN = 0; // to clear error, reception module must be reset RCSTA2bits.CREN = 1; RCREG2; // dummy read - part of module reset RCREG2; // dummy read *rec = nack; // current setting: if(OERR); discard data and re-transimission } // MINOR ERROR - framing else if(RCSTA2bits.FERR){ RCREG2; // dummy read - part of module reset *rec = nack; // current setting: if(FERR); discard data and re-transmission } // NORMAL OPERATION else{ *rec = RCREG2; // store received data to "rec" } } // ISR WHEN REQUEST FOR RECEPTION HAPPENS void __interrupt() high_isr(void){ INTCONbits.GIEH = 0; if(PIR3bits.RC2IF){ uart_receive(&data_rec); isr_flag = 1; } INTCONbits.GIEH = 1; } void main(void) { TRISC = 0; TRISD = 0; LATC = 0; LATD = 0; osc_initialize(); uart_initialize(); uint8_t data_tran[] = {"ABCDE"}; //character set to be transmitted while(1){ for(int i = 0; data_tran; i++){ // GENERATE DELAY WHILE CONTINUOUSLY CALL TRANSMISSION for(float j = 0; j < 5; j += 0.1){ uart_transmit(&data_tran); } } } return; }
代码的解释:从main(),我呼吁uart_transmit()函数,它传送一个字符的时间(和产生足够的延迟,所以我可以观察到数据传输LED条形图(连续接收的数据并行输出PORTD))。字符发送后,发射机只是从接收器等待ACK的传播或纳——如果它ACK,传递下一个字符;如果它被纳,重新发送当前字符直到ACK。
至于接收机,它等待在main()为ISR请求(循环)。数据加载到RSR登记后,uart_read()函数执行。如果收到的数据没有任何错误,数据输出PORTD,发送ACK发射机和程序返回主()。如果有一个错误关于接待的性格,PORTD数据保持不变(错误数据被丢弃),纳发送到发射机和程序返回主要(),在那里等待重新传输的性格。

现实生活中实现:首先,程序甚至不会正确地开始,如果TX和RX线路(设备)的两边不稍微加载(添加1 m欧姆电阻接地在双方两针)。否则,项目按预期的方式工作,如果没有特殊事件,如隔离的数据行(和触发的FERR发射机或接收机模拟错误处理)。如果发生这种情况,领导表明程序遍历“错误”路径无关的但是当我往回连接线路,路径回到“正常运行”只不时(这是最奇怪的事实)。同时,重置两个设备同时也不时地工作。

结论(问题):我觉得有一些问题关于计时,当错误是(或应该是)复位和程序是(或应该)回到“正常运行”的道路。然而,我不能理解,我定时误差失踪。
字符传输后,F452等到TSR是空的(即使没有必要,因为它等待ACK /克)。F452接收到字符后,uart_receive()之后才RSR充满ACK /克”传播,uart_transmit()立即结束,而不是等待TMRT设置——因为项目需要回到uart_receive()然后回到ISR回主()在新的中断之前由于从46 k80重新传输。

考虑时间的事实,我真的自己不能进一步解决这个问题。

编辑:我意识到需要上拉电阻UART正常运作(RX不是捡噪音),但听觉后,现在该项目甚至不开始执行;也就是说,数据不会开始传输并没有显示任何错误。
另一个事实是,当它工作(如果没有使用电阻器),也应该从发射机传输的数据如果任何数据行断开连接;也就是说,如果任何错误触发。但它不是传播——只要任何错误出现,TX线(发射机)高。

主持人注意:代码标记用于代码

附件

主持人:最后编辑的
T

trebla

加入2019年6月29日
316年
我认为你必须重写代码以更加结构化的方式。首先,你的流程图和代码不匹配。在TX代码()循环(在main()函数)定义了数组data_tran[],而不是单一的整数值。你在中断例程调用接收函数从而增加中断延迟。制定好计划(流程图)和遵循。
Papabravo

Papabravo

2006年加入2月24日
15620年
这是非常低效的带宽利用率的角度。除了在异步通信开销有2或3每8位数据位负载你的带宽利用率低于50%。得到可靠通信噪声信道上你想实现一个计划的错误检测概率高和重传的成本低比特误码率。你似乎没有做作业。好的错误检测可以用CRC检查字。还你想要包装或纳整个数据包,而不是单个字符。
班

加入,2019年1月27日
2822年
这是非常低效的带宽利用率的角度。除了在异步通信开销有2或3每8位数据位负载你的带宽利用率低于50%。得到可靠通信噪声信道上你想实现一个计划的错误检测概率高和重传的成本低比特误码率。你似乎没有做作业。好的错误检测可以用CRC检查字。还你想要包装或纳整个数据包,而不是单个字符。
我想去,但是首先我想了解接收者知道证实或否定。
班

加入,2019年1月27日
2822年
如果框架(FERR)或溢出(OERR)错误发生在接收数据时,接收器传输NACK,否则ACK。

如果有其他任何澄清,我愿意解释。,)
我想我有困难提供帮助,因为我不明白你的目标。这是一个实际的项目吗?它是学习什么?如果是这样,你想了解什么?

我问,因为我看不到任何实际应用,我不知道为什么要使用一些完全不切实际的学习工具。
鲁卡

线程启动

鲁卡

加入1月25日,2018年
12
如果框架(FERR)或溢出(OERR)错误发生在接收数据时,接收器传输NACK,否则ACK。

如果有其他任何澄清,我愿意解释。:D
我认为你必须重写代码以更加结构化的方式。首先,你的流程图和代码不匹配。在TX代码()循环(在main()函数)定义了数组data_tran[],而不是单一的整数值。你在中断例程调用接收函数从而增加中断延迟。制定好计划(流程图)和遵循。
关于流程图和代码流程图我试图只考虑代码的主要方面(降低复杂性,提高可读性)。
数组的定义data_tran []因为我想发送一个字符数组(当然一个接一个)。有什么不对吗?
关于ISR,我同意调用函数从它也增加了整个程序的复杂性和性能,为ISR应尽快终止。我将试着解决这个。
djsfantasi

djsfantasi

2010年加入4月11日
7602年
这是非常低效的带宽利用率的角度。除了在异步通信开销有2或3每8位数据位负载你的带宽利用率低于50%。得到可靠通信噪声信道上你想实现一个计划的错误检测概率高和重传的成本低比特误码率。你似乎没有做作业。好的错误检测可以用CRC检查字。还你想要包装或纳整个数据包,而不是单个字符。
完全同意100%。这是一个不切实际的,我敢说可笑的设计。我想不出任何通信应用程序与数据包大小为1。没有必要。的开销是低效的。你减少60%的带宽。根据传输的字节数的来源,你会失去你的数据在处理ACK / NAK协议。

因为你有一个字符数组,为什么不计算CRC值在一个传输和发送整个数组。在接收端通过重新计算CRC和比较收到的CRC码,然后你就可以ACK /否定整个数组/传播。
鲁卡

线程启动

鲁卡

加入1月25日,2018年
12
我想我有困难提供帮助,因为我不明白你的目标。这是一个实际的项目吗?它是学习什么?如果是这样,你想了解什么?

我问,因为我看不到任何实际应用,我不知道为什么要使用一些完全不切实际的学习工具。
为什么你认为学习是UART的工作方式和错误处理,以确保“安全”和“稳定”通信是不切实际的?
实际上,这是我第一次(小)项目在两个数字组件之间的通信(微处理器)——我选择它,因为UART应该比较容易理解和实现。

我想了解如何实现至少某种数字通信在嵌入式系统——因为它是任何项目的基础,需要两个或两个以上数字组件之间的接口(如微处理器之间的连接和TFT或液晶显示)。

UART可能不会使用这些天,但在我看来是足够好的。我不是说我要用它控制航天飞机. .:D但学习不够好,在我进行一些其他的,更实际的形式的数字通信。

还我只是一个初学者嵌入式系统和C编程所以我认为一个项目两个设备之间建立良好的UART通信是足够好的项目开始。
班

加入,2019年1月27日
2822年
如果你想学习如何创建一个可靠的通道设备之间我希望你将从一个简单的开始实用这不是例子。为什么不使用的东西是它的真正含义做出可靠的频道吗?

只是因为你想学习并不意味着你必须扔掉一切实用。做实际的事情是学习的方式。

当然,在任何情况下,它是完全取决于你如何选择学习但你是要求人们帮助您调试部分车的东西,因为你没有使用实际的代码。

谢谢你的回答,祝你好运在你的学习、数据通信可以有很多乐趣。
鲁卡

线程启动

鲁卡

加入1月25日,2018年
12
这是非常低效的带宽利用率的角度。除了在异步通信开销有2或3每8位数据位负载你的带宽利用率低于50%。得到可靠通信噪声信道上你想实现一个计划的错误检测概率高和重传的成本低比特误码率。你似乎没有做作业。好的错误检测可以用CRC检查字。还你想要包装或纳整个数据包,而不是单个字符。
我认为这是非常无效的但是,我不想深入效率在一开始的理解相对简单的UART通信应该是如何运作的。我不只是想明确的错误,像什么都没有发生——这可能会导致问题,不同的关键是每个字节的数据接收器。
“数据包”是如何定义的?我应该检查每10个字节或每1000个字节错误?可能取决于错误发生的可能性(由于外界噪声、电网峰值附近的射频传输,等等)。
现在,我只是考虑框架或溢出错误;我不处理数据完整性(腐败的单个或多个比特),来了之后,在我建立一些稳定的两个微处理器之间的通信形式。
鲁卡

线程启动

鲁卡

加入1月25日,2018年
12
如果你想学习如何创建一个可靠的通道设备之间我希望你将从一个简单的开始实用这不是例子。为什么不使用的东西是它的真正含义做出可靠的频道吗?

只是因为你想学习并不意味着你必须扔掉一切实用。做实际的事情是学习的方式。

当然,在任何情况下,它是完全取决于你如何选择学习但你是要求人们帮助您调试部分车的东西,因为你没有使用实际的代码。

谢谢你的回答,祝你好运在你的学习、数据通信可以有很多乐趣。
我同意一些点,直接跳到最实用的数据通信可能是一个更好的开始。但是,UART(可能)的其他串行通讯的基础。理解它(主要是基本)通过一个简单的项目不会伤害,我猜。
另外,我目前使用的两个图片都有“集成”硬件EUSART块(对这类通信)进行了优化。我想试试它唯一的自然,理解它(如果可能的话),实现一个简单的项目实施,继续下一个话题。

谢谢你,考虑理解解释主题!
班

加入,2019年1月27日
2822年
我同意一些点,直接跳到最实用的数据通信可能是一个更好的开始。但是,UART(可能)的其他串行通讯的基础。理解它(主要是基本)通过一个简单的项目不会伤害,我猜。
另外,我目前使用的两个图片都有“集成”硬件EUSART块(对这类通信)进行了优化。我想试试它唯一的自然,理解它(如果可能的话),实现一个简单的项目实施,继续下一个话题。

谢谢你,考虑理解解释主题!
要清楚一点,使用UART并不是问题。物理层可以不管,误差修正方案,不是很有用。一点实际研究纠错建议几个简单的方案不是更难代码(如果有的话),将是一个更好的起点。

如果你只是想学习UART的工作,把错误的东西和两者之间的沟通。然后加入校正,但如果在做它,我使用一些更符合你想要做什么实际上做一个可靠的渠道。
鲁卡

线程启动

鲁卡

加入1月25日,2018年
12
要清楚一点,使用UART并不是问题。物理层可以不管,误差修正方案,不是很有用。一点实际研究纠错建议几个简单的方案不是更难代码(如果有的话),将是一个更好的起点。

如果你只是想学习UART的工作,把错误的东西和两者之间的沟通。然后加入校正,但如果在做它,我使用一些更符合你想要做什么实际上做一个可靠的渠道。
我忘了说,之前我已经设置工作UART com始于纠错(在此之前我只是清除错误和移动)。那件事按预期工作。但也比现在更简单的代码。

你能用下面的精致的你是什么意思?
我使用一些更符合你必须做些什么来实际上做一个可靠的渠道。
谢谢!
djsfantasi

djsfantasi

2010年加入4月11日
7602年
如果我可能会增加,这是有点像学习开车。一个手推车可以学习,但实际上,不会帮助你得到你的许可。

错误检测和纠正单个字节是你的手推车。但它不会帮助你开车在高速公路上。
鲁卡

线程启动

鲁卡

加入1月25日,2018年
12
完全同意100%。这是一个不切实际的,我敢说可笑的设计。我想不出任何通信应用程序与数据包大小为1。没有必要。的开销是低效的。你减少60%的带宽。根据传输的字节数的来源,你会失去你的数据在处理ACK / NAK协议。

因为你有一个字符数组,为什么不计算CRC值在一个传输和发送整个数组。在接收端通过重新计算CRC和比较收到的CRC码,然后你就可以ACK /否定整个数组/传播。
它不会与数据包大小为1,因为太慢了传播关于波特率?还是有其他原因?

正如前面提到的,我不关心(至少现在),速度和效率低下。来之后我设法实现操作如上所述传输没有这样出乎意料的活动(指“现实生活中实现”一节)。
班

加入,2019年1月27日
2822年
我忘了说,之前我已经设置工作UART com始于纠错(在此之前我只是清除错误和移动)。那件事按预期工作。但也比现在更简单的代码。

你能用下面的精致的你是什么意思?


谢谢!
我的意思是,你的计划在实践中不能使用的通道更可靠,因为它是完全天真的和低效的。串行连接的误比特率是众所周知的了。处理这些问题的方案,这看起来不像你也记录了无处不在。甚至天真的计划,至少使用的数据块将更有意义。你“纠正”的错误冗余如果你检查实际数据的错误。一个简单的校验和,或通过CRC数据会让你开始在可靠的数据传输。

包的大小可以被预期的误码率计算(比特误码率)的通道。我真的认为你会找到更多的学习做一个简单但实用的误差修正方案。
鲁卡

线程启动

鲁卡

加入1月25日,2018年
12
如果我可能会增加,这是有点像学习开车。一个手推车可以学习,但实际上,不会帮助你得到你的许可。

错误检测和纠正单个字节是你的手推车。但它不会帮助你开车在高速公路上。
我的意思是,是否程序检查的有效性数据每一个字节或每1000个字节不应该是困难的任务来实现。然而,我还没有尝试过任何数据验证算法的CRC、校验和,平价,等等。