问题描述
在我的项目中,我需要通过 UART 连接一个 PIC32MZ2048EFH144 和一个外部设备。我使用 Harmony v1.1 以这种方式设置 USART 外设:
CONfig_USE_DRV_USART=y
CONfig_DRV_USART_DRIVER_MODE="STATIC"
CONfig_DRV_USART_INTERRUPT_MODE=y
CONfig_DRV_USART_BYTE_MODEL_SUPPORT=n
CONfig_DRV_USART_READ_WRITE_MODEL_SUPPORT=n
CONfig_DRV_USART_BUFFER_QUEUE_SUPPORT=y
CONfig_DRV_USART_SUPPORT_TRANSMIT_DMA=n
CONfig_DRV_USART_SUPPORT_RECEIVE_DMA=n
CONfig_DRV_USART_INSTANCES_NUMBER=2
CONfig_DRV_USART_CLIENTS_NUMBER=2
CONfig_DRV_USART_PERIPHERAL_ID_IDX1="USART_ID_4"
CONfig_DRV_USART_BAUD_RATE_IDX1=9600
CONfig_DRV_USART_XMIT_INT_PRIORITY_IDX1="INT_PRIORITY_LEVEL1"
CONfig_DRV_USART_XMIT_INT_SUB_PRIORITY_IDX1="INT_SUBPRIORITY_LEVEL0"
CONfig_DRV_USART_RCV_INT_PRIORITY_IDX1="INT_PRIORITY_LEVEL1"
CONfig_DRV_USART_RCV_INT_SUB_PRIORITY_IDX1="INT_SUBPRIORITY_LEVEL0"
CONfig_DRV_USART_ERR_INT_PRIORITY_IDX1="INT_PRIORITY_LEVEL1"
CONfig_DRV_USART_ERR_INT_SUB_PRIORITY_IDX1="INT_SUBPRIORITY_LEVEL0"
CONfig_DRV_USART_OPER_MODE_IDX1="DRV_USART_OPERATION_MODE_norMAL"
CONfig_DRV_USART_INIT_FLAG_WAKE_ON_START_IDX1=n
CONfig_DRV_USART_INIT_FLAG_AUTO_BAUD_IDX1=n
CONfig_DRV_USART_INIT_FLAG_STOP_IN_IDLE_IDX1=n
CONfig_DRV_USART_LINE_CNTRL_IDX1="DRV_USART_LINE_CONTROL_8NONE1"
CONfig_DRV_USART_HANDSHAKE_MODE_IDX1="DRV_USART_HANDSHAKE_NONE"
CONfig_DRV_USART_XMIT_QUEUE_SIZE_IDX1=10
CONfig_DRV_USART_RCV_QUEUE_SIZE_IDX1=10
CONfig_DRV_USART_STATIC_RX_MODES_IDX1="USART_HANDSHAKE_MODE_FLOW_CONTROL"
CONfig_DRV_USART_STATIC_OP_MODES_IDX1="USART_ENABLE_TX_RX_USED"
CONfig_DRV_USART_STATIC_LINECONTROL_MODES_IDX1="USART_8N1"
CONfig_DRV_USART_STATIC_TX_ENABLE_IDX1=y
CONfig_DRV_USART_STATIC_RX_ENABLE_IDX1=y
CONfig_DRV_USART_STATIC_TX_INTR_MODES_IDX1="USART_TRANSMIT_FIFO_NOT_FULL"
CONfig_DRV_USART_STATIC_RX_INTR_MODES_IDX1="USART_RECEIVE_FIFO_ONE_CHAR"
一开始,外部设备发送一条唤醒消息,我正确接收并回复唤醒确认。 在这个序列之后,我发送了一个 requestDevID ...在这一点上我遇到了一些麻烦。通过示波器,我可以看到外部设备正确回答了这个请求,但在我的代码中我没有得到完整的消息。
答案是:0xFA 0xFF 0x01 0x04 0x07 0x78 0x26 0x1A 0x3D 我看到的(当我停止调试时)是:0x78 0x26 0x1A 0x3D 0x07
我的代码如下:
void mti710USART1BufferHandler(DRV_USART_BUFFER_EVENT bufferEvent,DRV_USART_BUFFER_HANDLE hBufferEvent,uintptr_t context){
switch(bufferEvent){
case DRV_USART_BUFFER_EVENT_COMPLETE:{
if (context == 1){
// to-do
flag = 1;
countFlag += 1;
}
break;
case DRV_USART_BUFFER_EVENT_ERROR:{
if (context == 1){
// to-do
flag = -1;
}
}
break;
case DRV_USART_BUFFER_EVENT_ABORT:
break;
default:
break;
}
}
bool mti710Initialize(MTi710INSInitDriver_t mti710Init){
mtiData.dvrMTi710INSIndex = mti710Init.dvrMTi710INSIndex;
mtiData.drvUART.handle = DRV_HANDLE_INVALID;
mtiData.drvUART.baudrate = 115200;
memset(&mtiData.drvUART.TX.buffer,0x00,sizeof(mtiData.drvUART.TX.buffer));
memset(&mtiData.drvUART.RX.buffer,sizeof(mtiData.drvUART.RX.buffer));
mtiData.drvUART.handle = DRV_USART_Open(mtiData.dvrMTi710INSIndex,DRV_IO_INTENT_READWRITE | DRV_IO_INTENT_NONBLOCKING);
if (mtiData.drvUART.handle != DRV_HANDLE_INVALID) {
if (mti710SetBaudrate(mtiData.drvUART.handle,mtiData.drvUART.baudrate)){
DRV_USART_BufferEventHandlerSet(mtiData.drvUART.handle,mti710USART1BufferHandler,(uintptr_t) 1);
mtiData.drvMti710INsstate = MTi710INS_STATE_IDLE;
return true;
}
}
return false;
}
static void UARTRead(uint8_t* readBuffer,uint32_t bufferSize){
USART_ReceiverOverrunErrorClear_Default(DRV_USART_INDEX_1);
while (DRV_USART_ClientStatus(mtiData.drvUART.handle) != DRV_USART_CLIENT_STATUS_READY);
DRV_USART_BufferAddRead(mtiData.drvUART.handle,&(mtiData.drvUART.RX.bufferHandle),readBuffer,bufferSize);
}
...
...
uint32_t mti710Readdeviceid(struct XbusParser* parser,const uint32_t timeout_us){
struct XbusMessage requestId = {XMID_ReqDid,NULL};
mtiData.drvMti710INsstate = MTi710INS_REQ_READ_ID;
if (flag == 0){
mti710WriteData(&requestId);
flag = 0;
}
mti710ReadData(9);
if (flag == 1){
XbusParser_parseBuffer(parser,(uint8_t*)&mtiData.drvUART.RX.buffer[0],sizeof(mtiData.drvUART.RX.buffer));
flag = 0;
return parser->currentMessage.mid == XMID_deviceid ? (uint32_t)parser->currentMessage.data : -1;
} else {
return -1;
}
}
知道我的错误吗?
问候,
文森佐。
解决方法
第一件事:
当您从应用程序代码中读取硬件寄存器(如 UART RX 寄存器)时,您必须禁用 UART RX 中断。
UART RX 寄存器是共享资源。
UART RX 寄存器由应用程序代码(在后台执行)和中断代码(在前台执行)共享。
如果您不禁用 UART RX 中断,则您的应用程序代码可能会在读取过程中中断并出现错误。
共享资源必须这样读取:
char a;
uart__disable_rx_interrupt(); // Begin of critical section
a = UART_RX_REGISTER;
uart__enable_rx_interrupt(); // End of critical section
然而:
应用程序代码不应过于频繁地禁用 UART RX 中断,因为 UART 接口可能会错过一些传入数据。
这件事发生在 1996 年。
理想的代码应用程序代码应为 9600 波特率:
char a;
sleep(100); // 100 ms
uart__disable_rx_interrupt(); // Begin of critical section
a = UART_RX_REGISTER;
uart__enable_rx_interrupt(); // End of critical section
printf(a);
最后一件事;
通常,数据被放置在环形缓冲区中
sleep(100); // 100 ms
uart__disable_rx_interrupt(); // Begin of critical section
a = UART_RX_REGISTER;
uart__write_in_ring_buffer(a);
uart__enable_rx_interrupt(); // End of critical section
uart__write_in_ring_buffer(&ch);
printf(ch);
建议您阅读 Jean Labrosse 的书:“https://www.amazon.it/Embedded-Systems-Building-Blocks-Ready/dp/0879304405”
研究Jean使用环形缓冲区编写的UART设备驱动程序。