主意:我正在尝试在发射机和接收器之间建立坚定的通信;坚定了解一些基本错误处理。我正在尝试实现ACK(确认)/ nack(负确认)风格的错误处理。我目前只是从一个设备(PIC18F46K80)传输数据并接收与其他一个(PIC18F452),其中发射机(T)发送“有用”数据和接收器(R)接受该数据并发送回变送器ACK或NACK每个数据的每个字节发送。
设置:由于对程序有一些复杂性,因此我为每个发射机和接收器制作了流程图(仅考虑代码的主要方面)。
这是发射机的代码(pic18f46k80)。接收方的代码不一样,但与此类似。Also, I use LEDs to indicate current position of program execution (e.g. when program is looping through "error" path or when is looping through "normal operation" path) and received data interpretation (LED bar graph connected in parallel to PORTD) but this is not included here (to improve code readability):
代码说明:来自Main(),我正在呼吁UART_TRANSMIT()函数,该函数在时间(并产生足够的延迟,所以我可以观察到LED条形图上的发送数据(串行接收的数据并行地输出到PORTD))。在发送字符之后,发送器只需等待来自接收器的ACK或NACK的传输 - 如果它获得ACK,则传输下一个字符;如果它得到NACK,请重新传输当前字符,直到它获得ACK。
至于接收器,它会在Main()(循环中)等待ISR请求。将数据加载到RSR寄存器中后,执行UART_READ()函数。如果在没有任何错误的情况下收到数据,则在Portd上输出数据,将ACK发送到发送器和程序返回Main()。如果关于接收字符的错误,则PORTD上的数据保持不变(丢弃不良数据),NACK将发送到发送器和程序返回到MAIN(),在那里它等待重新传输字符。
现实生活中实现:首先,如果TX和RX线(在设备的两侧)都没有略微加载(在两侧的两个引脚上向GND添加1M欧姆电阻向GND添加1M欧姆电阻),则程序甚至不会正确地开始正确。否则,程序按预期工作,如果没有特殊事件,例如断开数据线的连接(并触发发送器或接收器中的任何一个)以模拟错误处理)。如果发生这种情况,LED指示程序循环通过“错误”路径循环,但随着我连接的未连接线,路径返回到“正常操作”(这是最奇怪的事实)。此外,重置两个设备同时也可以不时工作。
结论(问题):我怀疑有一些关于时间的问题,当错误是(或应该是)重置和程序是(或应该是)返回到“正常的操作”路径。然而,我不明白,我在这里错过了什么时间错误。
在传输字符之后,F452等待直到TSR为空(即使在这里不需要那么),因为它等待ACK / NACK)。在F452接收到字符之后,只有在RSR完全且传输ACK / NACK之后仅调用UART_RECEIVE(),立即结束 - 不等待设置TMRT - 因为程序需要返回UART_RECEIVE()然后回到ISR然后在新中断发生之前返回Main(),因为重新传输从46K80重新传输。
考虑到所有这些时机事实,我真的无法通过自己进一步解决这个问题。
编辑:我意识到UART需要上拉电阻器正常运行(RX未拾取噪音),但在重新接线之后,现在程序甚至无法开始执行;也就是说,数据无法开始发送,并且我也没有任何错误的指示。
另一个事实是,当它有效(如果没有使用电阻)时,如果任何数据线断开连接,则应从发射器传输数据;也就是说,如果有任何错误触发。但它没有传输 - 一旦任何错误显示出来,TX线(变送器)就会变高。
版主注意:用于代码的代码标签
设置:由于对程序有一些复杂性,因此我为每个发射机和接收器制作了流程图(仅考虑代码的主要方面)。
这是发射机的代码(pic18f46k80)。接收方的代码不一样,但与此类似。Also, I use LEDs to indicate current position of program execution (e.g. when program is looping through "error" path or when is looping through "normal operation" path) and received data interpretation (LED bar graph connected in parallel to PORTD) but this is not included here (to improve code readability):
C:
#include #include #include #include“config_bits.h”void osc_initialize(void);void uart_initialize(无效);voidUART_RECEIVE(UINT8_T * C);void UART_TRANSMIT(UINT8_T * C);void __interrupt()high_isr(void);uint8_t data_rec;//收到数据存储变量UINT8_T ISR_FLAG = 0;//用于指示ISR UINT8_T ACK = 0x06的完成;//确认代码UINT8_T NACK = 0x15;//否定确认代码// intialize内部振荡器寄存器void osc_initialize(void){osconbits.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()(循环中)等待ISR请求。将数据加载到RSR寄存器中后,执行UART_READ()函数。如果在没有任何错误的情况下收到数据,则在Portd上输出数据,将ACK发送到发送器和程序返回Main()。如果关于接收字符的错误,则PORTD上的数据保持不变(丢弃不良数据),NACK将发送到发送器和程序返回到MAIN(),在那里它等待重新传输字符。
现实生活中实现:首先,如果TX和RX线(在设备的两侧)都没有略微加载(在两侧的两个引脚上向GND添加1M欧姆电阻向GND添加1M欧姆电阻),则程序甚至不会正确地开始正确。否则,程序按预期工作,如果没有特殊事件,例如断开数据线的连接(并触发发送器或接收器中的任何一个)以模拟错误处理)。如果发生这种情况,LED指示程序循环通过“错误”路径循环,但随着我连接的未连接线,路径返回到“正常操作”(这是最奇怪的事实)。此外,重置两个设备同时也可以不时工作。
结论(问题):我怀疑有一些关于时间的问题,当错误是(或应该是)重置和程序是(或应该是)返回到“正常的操作”路径。然而,我不明白,我在这里错过了什么时间错误。
在传输字符之后,F452等待直到TSR为空(即使在这里不需要那么),因为它等待ACK / NACK)。在F452接收到字符之后,只有在RSR完全且传输ACK / NACK之后仅调用UART_RECEIVE(),立即结束 - 不等待设置TMRT - 因为程序需要返回UART_RECEIVE()然后回到ISR然后在新中断发生之前返回Main(),因为重新传输从46K80重新传输。
考虑到所有这些时机事实,我真的无法通过自己进一步解决这个问题。
编辑:我意识到UART需要上拉电阻器正常运行(RX未拾取噪音),但在重新接线之后,现在程序甚至无法开始执行;也就是说,数据无法开始发送,并且我也没有任何错误的指示。
另一个事实是,当它有效(如果没有使用电阻)时,如果任何数据线断开连接,则应从发射器传输数据;也就是说,如果有任何错误触发。但它没有传输 - 一旦任何错误显示出来,TX线(变送器)就会变高。
版主注意:用于代码的代码标签
附件
-
237.8 KB 意见:9
-
4.1 KB. 意见:1
-
4 KB. 意见:0
最后编辑了主持人: