老大分配了个任务给我,使用的是STM32G431C8芯片;处于学习的目的,打算将整个项目的驱动层自己手把手配一遍,期间遇到了一些问题,然后有些问题是以前遇到过的,就一并归纳到这里,记录一下,以防以后再掉进这个坑里
空闲中断时候会触发串口中断,串口中断不会触发空闲中断,所以在串口中断服务函数里面做判断的时候需要注意两者的优先级(即先后顺序);
void USART2_IRQHandler(void) { /* USER CODE BEGIN USART2_IRQn 0 */ static char count_char=0; //测试用的 /* USER CODE END USART2_IRQn 0 */ HAL_UART_IRQHandler(&huart2); /* USER CODE BEGIN USART2_IRQn 1 */ if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE)!=RESET){ //是空闲中断,关停DMA,转移DMA过来的数据,复位DMA的计数,重新打开DMA,清除空闲中断 __HAL_UART_CLEAR_IDLEFLAG(&huart2); HAL_UART_DMAStop(&huart2); uint8_t data_length = 200 - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx); HAL_UART_Transmit_DMA(&huart2,usart2_rxbuf,data_length); //转发出去 //这里我将数据原路转发了,需要的话可以自己加环形队列处理 HAL_UART_Receive_DMA(&huart2, (uint8_t*)usart2_rxbuf,200); } else if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE)!=RESET){ //触发IDLE的时候也会触发RXNE usart2_rxbuf[count_char++]=USART2->RDR; __HAL_UART_CLEAR_FLAG(&huart2,UART_FLAG_RXNE); //同时清掉了IDLE if(count_char == 10){ count_char=0; } }在上述情况下,发现有时候如果发送端发送频率太快的话,串口虽然仍然工作和回传,但是回传的数据一直都是错误的,初步判断是buffer的size太小(瞎猜的);只能选择从DMA中断函数下刀了:
void DMA1_Channel5_IRQHandler(void) { /* USER CODE BEGIN DMA1_Channel5_IRQn 0 */ HAL_UART_DMAStop(&huart2); /* USER CODE END DMA1_Channel5_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_usart2_rx); /* USER CODE BEGIN DMA1_Channel5_IRQn 1 */ //防止卡死,重新开启一下DMA HAL_UART_Receive_DMA(&huart2, (uint8_t*)usart2_rxbuf,200); /* USER CODE END DMA1_Channel5_IRQn 1 */ }下一次写博客不知道又是啥时候了,先咕再说;
为了方便交互,定义了一个结构体
typedef struct{ char request_type; uint32_t ptr; }Param_Package;在task1往RTOS队列里面写一条请求,由task2进行响应
Param_Package param_request; param_request.request_type=0; //写指令 param_request.ptr=(uint8_t *)RWBuffer; //存放变量地址; xQueueSend(CAN_to_E2RomDataQueueHandle,¶m_request,0); //通过队列发送写指令在task2中进行接收处理及响应:
if(xQueueReceive(CAN_to_E2RomDataQueueHandle,¶m_req,0)==pdTRUE){ if(param_req.request_type==0){ //写请求 memcpy(&app_param.crc,(uint8_t *)param_req.ptr,4); //uint32_t crc uint32_t crc_=crc16_calculate_e(((uint8_t*)param_req.ptr+4),sizeof(app_param.mqtt_param)); if(crc_ == app_param.crc){ //crc校验通过 //Update Param AT24CXX_Write(PARAM_BASE_ADDR,param_req.ptr,sizeof(app_param.mqtt_param)+4); //存入E2ROM param_res.request_type=1; //参数更改成功 param_res.ptr=0; }else{ //crc校验不通过 //【存在的问题:不能上报错误信息?】 param_res.request_type=0; //参数更改失败 param_res.ptr=0; //错误码 } xQueueSend(E2Rom_to_CANDataQueueHandle,¶m_res,0); //通过队列进行响应 }在task1中param_request.ptr为0x1ffc100 在task2中param_req.ptr为 0x1ffbd10 一开始猜测是以下几种情况导致的:①指针使用错误;②结构体成员数据类型错误;分别对这两种情况进行了尝试,但是情况依旧存在 后来用局部变量代替了buff[5]代替了结构体实例,两边实现了正常交互;然后碰巧在最近遇到过因为结构体字节对齐问题导致的sizeof()结果出错,于是尝试了在结构体前面增加向1字节对齐的宏
#pragma pack(1) //结构体按照1字节对齐 typedef struct{ char request_type; uint32_t ptr; //针对responce 是否要做错误码 }Param_Package;报错信息: invalid type argument of ‘->’ (have 'struct ')
/** * @brief 获取软件编译时间 * * @param app_msg * @return 指针返回 */ static void Hard_Time_Get(App_param* point){ uint32_t date=0; uint32_t time=0; char str_[50]; uint32_t year,month,day; memcpy(str_,__DATE__,sizeof(__DATE__)); memcpy(str_+sizeof(__DATE__)-1,__TIME__,sizeof(__TIME__)); year=(str_[7])*10000000 + (str_[8])*1000000 + (str_[9])*100000 +(str_[10])*10000; date+=year; switch(str_[0]+str_[1]+str_[2]){ case JAN: month=1; break; case FEB: month=2; break; case MAR: month=3; break; case APR: month=4; break; case MAY: month=5; break; case JUN: month=6; break; case JUL: month=7; break; case AUG: month=8; break; case SEP: month=9; break; case OCT: month=10; break; case NOV: month=11; break; case DEC: month=12; break; } date+=month*100; day=(str_[4])*10+(str_[5]); date+=day; date-=(0x30)*11110011; point->tbox_param.EditDate=date; time=(str_[11])*100000+(str_[12])*10000+(str_[14])*1000+(str_[15])*100+(str_[17])*10+(str_[18]); time-=(0x30)*111111; point->tbox_param.EditTime=time; }point->tbox_param->EditDate=date; 这种写法就会导致上面的报错 point->tbox_param.EditDate=date; 这种写法才是正确的