硬件平台:STM32F407开发平台:Keil MDK
问题现象:
我使用FreeRTOS 创建了2个任务。这两个任务中,都会对同一个全局变量数组进行修改。但是任务2只有按键按下了才会修改。任务1:启动串口DMA发送数据固定格式的“读数据帧”。并检测写标志是否置1,置1则发送写数据
[C] 纯文本查看 复制代码 void Master_SendPackagetoSubcotrol(void)
{
static uint8_t s_Current_ID = 0;
uint16_t crc_check = 0;
if(g_ucRS485ReadWriteFlag)
{
g_ucRS485ReadWriteFlag = 0;
}
else
{
g_RS422TxBuf[0] = 0x24;
g_RS422TxBuf[1] = g_buffSubcontrolID[s_Current_ID];
g_RS422TxBuf[2] = 0xFF;
g_RS422TxBuf[3] = 0x03;
g_RS422TxBuf[4] = 0x00;
g_RS422TxBuf[5] = 0x36;
g_RS422TxBuf[6] = sizeof(ModuleData_T);//数据长度 字节计算
g_RS422TxBuf[7] = 10;
s_Current_ID++;
if(s_Current_ID >= SUBMODULE_NUM+1)s_Current_ID = 0;
crc_check = 0x55AA;
g_RS422TxBuf[g_RS422TxBuf[7]-2] = U16_LowByte(crc_check);
g_RS422TxBuf[g_RS422TxBuf[7]-1] = U16_HighByte(crc_check);
}
//启动DMA传输
if(DMA_GetFlagStatus(RS485_USART_DMA_STREAM, RS485_USART_DMA_TCIF_FLAG) != RESET)//等待DMA2_Steam7传输完成
{
DMA_ClearFlag(RS485_USART_DMA_STREAM, RS485_USART_DMA_TCIF_FLAG);//清除DMA2_Steam7传输完成标志
}
DMA_Enable(RS485_USART_DMA_STREAM, g_RS422TxBuf[7]); //开始一次DMA传输!
}
任务2:按键按下了,修改全局变量数组,发送“写数据帧”标志置1。等待任务1中检测到标志后启动发送。
[C] 纯文本查看 复制代码 void delete_key_up(void)
{
if(key_in() == 1)
{
g_ucRS485ReadWriteFlag = 1;
g_RS422TxBuf[FRAME_INDEX_HEAD] = FRAME_HEAD;
g_RS422TxBuf[FRAME_INDEX_SLAVE_ID] = 0xff;
g_RS422TxBuf[FRAME_INDEX_DRIVER_ID] = 0xff;
g_RS422TxBuf[FRAME_INDEX_OPERATE] = FRAME_OPERATE_WRITE;
g_RS422TxBuf[FRAME_INDEX_ADDRESS_H] = 0;
g_RS422TxBuf[FRAME_INDEX_ADDRESS_L] = CMD_SubCOntrol_Write_GuideControlStatus;//写地址
g_RS422TxBuf[FRAME_INDEX_DATA_LENGTH] = 2;
g_RS422TxBuf[FRAME_INDEX_FRAME_LENGTH] = g_RS422TxBuf[FRAME_INDEX_DATA_LENGTH] + 10;
*(uint16_t *)(g_RS422TxBuf+FRAME_INDEX_DATA_H) = 0xCCCC;
crc_check = 0x55AA;
g_RS422TxBuf[g_RS422TxBuf[FRAME_INDEX_FRAME_LENGTH]-2] = U16_LowByte(crc_check);
g_RS422TxBuf[g_RS422TxBuf[FRAME_INDEX_FRAME_LENGTH]-1] = U16_HighByte(crc_check);
}
}
然后问题就来了。如果任务1中DMA刚刚启动完,然后任务2就把按键按下,修改了DMA传输内存中的值,造成了DMA数据数据的错乱。如下图所示:
其中,
24 06 FF 10 00 19 02 CC CC CC 就是传输错误,本来需要传输的是, 24 06 FF 03 00 36 00 0A AA 55,结果在传输的过程中被改变了导致错误。 那么在实际应用中该如何避免?
现在我的做法是,将检测按键的任务与发送数据的任务合为一个任务。并且,按键检测函数在前,发送函数在后可以避免该问题。
或者可以采用while()等待DMA发送完成,然后在执行任务调度,考虑到任务中采用死等的方式,会造成其他任务的不执行因此没有采用。
|