这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » 【GD32F527】在spi模拟时序不同编译优化等引起的通信异常以及解决方案

共1条 1/1 1 跳转至

【GD32F527】在spi模拟时序不同编译优化等引起的通信异常以及解决方案

工程师
2025-09-09 14:07:53     打赏

最近在调试GD32F527驱动XPT2046时,由于他的特殊时序,我采用软件模拟来实现spi通信,接收通信代码如下:

uint16_t XPT2046_recv_byte(void)
{		uint8_t i;
    uint16_t data = 0;
	  
    XPT2046_SCK_LOW();
    delay_5us();
    for(i=0; i<12; i++)
    {
        XPT2046_SCK_HIGH();
        delay_5us();
        XPT2046_SCK_LOW();
        data <<= 1;
        if(XPT2046_MISO_READ())
        {
            data |= 0x01;
        }
        delay_5us();
    }
		rt_kprintf("recv data:%u\n",data);
    return data&0x0FFF;
}

delay_5us的函数如下:

void delay_5us(void)
{
    for(uint8_t i=0; i<10; i++);
}

我在使用编译优化等级为-O0时,读取的通信正常,但是在使用-O3时发现读取出来的数全是0x00,经过查找原因,是因此优化后,延时的时间不对,引起通信异常。

【解决方法】

为了避免过度优化,我修改延时函数如下:

static void delay_5us(void)
{
    // 使用volatile变量确保循环不被优化掉
    volatile uint32_t count;
    // 根据实际硬件校准循环次数
    for(count = 0; count < 20; count++)
    {
        __NOP();  // 空操作,确保指令执行
    }
}

而后通信就正常了。

同时我也修改了一下接收函数:

/* 从XPT2046接收12位数据  */
uint16_t XPT2046_recv_byte(void)
{
    uint8_t i;
    uint16_t data = 0;
    // 确保变量不被编译器优化
    volatile uint8_t miso_state;
    
    // 对硬件操作添加内存屏障,防止编译器重排序
    __asm volatile("" : : : "memory");
    
    XPT2046_SCK_LOW();
    delay_5us();  // 确保延迟函数在高优化下仍能正常工作
    
    for(i = 0; i < 12; i++)
    {
        XPT2046_SCK_HIGH();
        delay_5us();
        
        XPT2046_SCK_LOW();
        // 读取MISO引脚状态,用volatile变量存储防止优化
        miso_state = XPT2046_MISO_READ();
        data <<= 1;
        if(miso_state)
        {
            data |= 0x01;
        }
        
        delay_5us();
        // 内存屏障,确保时序操作按顺序执行
        __asm volatile("" : : : "memory");
    }
    
    rt_kprintf("recv data:%u\n", data);
    return data & 0x0FFF;
}

这样修改后,读取数据就正常了:

image.png




关键词: GD32F527     模拟     编译     优化    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]