OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 144|回复: 2

F407仿真模式下数据正常,在芯片上异常???

[复制链接]

0

主题

1

帖子

0

精华

新手入门

积分
6
金钱
6
注册时间
2017-6-23
在线时间
4 小时
发表于 5 天前 | 显示全部楼层 |阅读模式
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嘛

回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165642
金钱
165642
注册时间
2010-12-1
在线时间
2122 小时
发表于 4 天前 | 显示全部楼层
在关键位置加入printf,串口辅助观察看看。一般调试模式可以,全速运行不行,可能是等待时间的问题
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
6
金钱
6
注册时间
2017-6-23
在线时间
4 小时
 楼主| 发表于 3 天前 | 显示全部楼层
正点原子 发表于 2025-12-2 21:21
在关键位置加入printf,串口辅助观察看看。一般调试模式可以,全速运行不行,可能是等待时间的问题

以你的经验,该在哪里加延时啊,延时时间多少??我用DMA读取数据,串口波特率是921600,数据传输频率是10Hz
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-12-6 08:36

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表