最近在调试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; }
这样修改后,读取数据就正常了: