新手入门
- 积分
- 6
- 金钱
- 6
- 注册时间
- 2017-6-23
- 在线时间
- 4 小时
|
1金钱
本帖最后由 648425145 于 2025-12-1 11:15 编辑
硬件用的XZM32F407ZG,用DMA读取的数据,在调试模式下测试数据正常,将程序烧录到单片机后数据就异常了,大家有遇到过嘛
DMA代码处理如下:
// 空闲中断处理 - 关键数据转移在中断中完成
void UART_Idle_Handler(UART_DMA_Manager *mgr)
{
if (mgr == NULL) return;
// 计算当前DMA写入位置
uint32_t dma_counter = __HAL_DMA_GET_COUNTER(mgr->hdma_rx);
uint32_t current_dma_pos = (UART_DMA_BUFFER_SIZE - dma_counter) % UART_DMA_BUFFER_SIZE;
// 计算新数据长度
uint32_t last_pos = mgr->last_dma_pos;
uint32_t new_data_len = 0;
if (current_dma_pos >= last_pos)
new_data_len = current_dma_pos - last_pos;
else
new_data_len = (UART_DMA_BUFFER_SIZE - last_pos) + current_dma_pos;
// 在中断中直接将数据转移到环形缓冲区
if (new_data_len > 0)
{
uint32_t transferred = 0;
if (current_dma_pos > last_pos)
// 连续数据块
transferred = RingBuffer_Write_FromISR(&mgr->ring_buffer,
&mgr->dma_buffer[last_pos],
new_data_len);
else
{
// 分两段处理
uint32_t first_chunk = UART_DMA_BUFFER_SIZE - last_pos;
transferred = RingBuffer_Write_FromISR(&mgr->ring_buffer,
&mgr->dma_buffer[last_pos],
first_chunk);
if ((transferred == first_chunk) && (current_dma_pos))
transferred += RingBuffer_Write_FromISR(&mgr->ring_buffer,
mgr->dma_buffer,
current_dma_pos);
}
// 更新统计信息
mgr->total_bytes_received += transferred;
mgr->last_dma_pos = current_dma_pos;
// 检查数据丢失
if (transferred < new_data_len)
mgr->dma_overflow_count++;
// 设置数据就绪标志(通知主循环)
if (transferred > 0)
mgr->data_ready_flag = 1;
}
// 清除空闲中断标志
__HAL_UART_CLEAR_IDLEFLAG(mgr->huart);
}
uint32_t UART_ProcessPacketsWithStateMachine(UART_DMA_Manager *mgr, PacketProcessor *processor,void (*packet_handler)(uint8_t *data, uint32_t length))
{
if (mgr == NULL || processor == NULL || packet_handler == NULL)
return 0;
uint32_t packets_processed = 0;
uint32_t data_count = RingBuffer_GetDataCount(&mgr->ring_buffer); //获取环形缓冲区的数据长度
static unsigned char Header_flag = 0; //帧头的类型标志
// 处理所有可用数据
while (processor->search_offset < data_count)
{
uint8_t current_byte;
if (RingBuffer_Peek(&mgr->ring_buffer, ¤t_byte, 1, processor->search_offset) != 1)
{
break;
}
int process_more = 1;
switch (processor->state)
{
case PKT_STATE_IDLE:
if (current_byte == SYNC_HEADER_0)
Header_flag = 1;
else if (current_byte == SYNC_CODE_0)
Header_flag = 2;
else
{
Header_flag = 0;
}
if (Header_flag)
{
processor->state = PKT_STATE_HEADER;
processor->packet_start = processor->search_offset;
processor->header_buffer[0] = current_byte;
processor->current_length = 1;
}
processor->search_offset++;
break;
case PKT_STATE_HEADER:
if ( ((Header_flag == 1) && (current_byte == SYNC_HEADER_1)) ||
((Header_flag == 2) && (current_byte == SYNC_CODE_1)) )
{
processor->state = PKT_STATE_LENGTH;
processor->header_buffer[1] = current_byte;
processor->current_length = 2;
}
else
{
Header_flag = 0;
processor->state = PKT_STATE_IDLE;
processor->search_offset = processor->packet_start + 1;
process_more = 0; // 重新处理当前位置
}
processor->search_offset++;
break;
case PKT_STATE_LENGTH:
processor->header_buffer[2] = current_byte;
processor->current_length++;
processor->search_offset++;
processor->state = PKT_STATE_SOURCE;
break;
case PKT_STATE_SOURCE:
processor->header_buffer[3] = current_byte;
processor->current_length++;
processor->search_offset++;
processor->state = PKT_STATE_DEST;
break;
case PKT_STATE_DEST:
processor->header_buffer[4] = current_byte;
processor->current_length++;
processor->search_offset++;
processor->state = PKT_STATE_DIRECTION;
break;
case PKT_STATE_DIRECTION:
processor->header_buffer[5] = current_byte;
processor->current_length++;
processor->search_offset++;
if(current_byte == FRAME_DL_TO_COORD)
processor->expected_length = 1210;
else
processor->expected_length = processor->header_buffer[2];
processor->state = PKT_STATE_PAYLOAD;
break;
case PKT_STATE_PAYLOAD:
{
uint32_t total_needed = processor->expected_length;
uint32_t available = data_count - processor->packet_start;
if (available >= total_needed)
{
// 读取完整包
uint8_t *packet_data = mgr->process_buffer;
if ((packet_data != NULL) && (total_needed <= sizeof(mgr->process_buffer)))
{
RingBuffer_Peek(&mgr->ring_buffer, packet_data,
total_needed, processor->packet_start);
packet_handler(packet_data, total_needed);
packets_processed++;
mgr->packets_received++;
}
// 消费数据并重置状态
Header_flag = 0;
RingBuffer_Consume(&mgr->ring_buffer, total_needed);
processor->state = PKT_STATE_IDLE;
processor->search_offset = 0; // 从头开始搜索
data_count = RingBuffer_GetDataCount(&mgr->ring_buffer);
process_more = 0; // 退出重新开始
}
else
{
// 数据不足,等待更多数据
//processor->state = PKT_STATE_IDLE;
//processor->search_offset = processor->packet_start;
return packets_processed;
}
}
break;
default:
processor->state = PKT_STATE_IDLE;
Header_flag = 0;
processor->search_offset++;
break;
}
if (!process_more)
{
break; // 需要重新开始处理
}
}
return packets_processed;
}
代码还啥bug嘛
|
|