上一篇文章解决了spi+dma传输数据时DC线操作时序不匹配的问题,但是屏幕依旧没有点亮,所以这一篇文章继续找还存在的问题。上一篇文章:沁恒微WCH32v003驱动ST7735S硬件spi+DMA调试小坑-CSDN博客
老规矩,先用逻辑分析仪抓取一下波形。
//全屏清除函数 void LCD_Clear(uint16_t color) { uint16_t i=0, j=0; uint8_t data[4] = {0}; //color是16bit的,每个像素点需要两个字节的显存 /* 将16bit的color值分开为两个单独的字节 */ data[0] = color >> 8; data[1] = color; /* 显存的值需要逐字节写入 */ for(j = 0;j < LCD_Buf_Size/2; j++) { lcd_buf[j * 2] = data[0]; lcd_buf[j * 2 + 1] = data[1]; } /* 指定显存操作地址为全屏幕 */ Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1); /* 指定接下来的数据为数据 */ LCD_DC_SET; /* 将显存缓冲区的数据全部写入缓冲区 */ LCD_Writ_Bus(data,4); for(i = 0;i <(LCD_TOTAL_BUF_SIZE/LCD_Buf_Size); i++) { LCD_Writ_Bus(lcd_buf, (uint16_t)LCD_Buf_Size); } }
这是我的全屏清除函数,用数组作为缓存,dma打包发送。
代码中我发送的全是oxff,但是实际上只有前面一半是0xff后面全是错乱的顺序,缩小给大家看一下。
正常来说全是0xff的话sda应该是一直高电平,但是有一半时间是不正常的,所以说明每次缓存区中都有一半的数据丢失了,使用数组的时候如果发现后面的数据不正常,大概率是因为数组访问越界了。
SPI+DMA的传输方式是发送地址不变,源地址不断自加,不断将源地址内的数据取出发送,所以我猜测是内存大小配置跟缓存区数组大小不匹配导致的。我们来验证一下这个猜测。
找到DMA的配置页面,其中标出的Halfwork就是半字的意思,也就是16位。
而我定义的缓存区是uint8_t,即是8位,所以也正好印证了我的猜想,就是DMA的内存位移跟缓存区的数据类型大小不匹配,DMA每次位移16位,而我的缓存区一个只有8位,因为数组中内存地址是连续的,所以DMA会在缓存区中隔一个数据发送,导致有一半的数据漏掉了,最后的一半数据都是数组越界访问得到的垃圾数据,所以后面一半数据是错乱的毫无意义的。
问题找到了,既然他们不匹配,那就让他们匹配呗,把uint8_t改成uint16_t不就就好了?
这个办法是可以的,可以看到数据已经全部变成0xff,说明传输已经正常了。但是有个问题,内存浪费,明明只有u8大小的数据却要用u16来存放,有一半的空间被浪费掉了,很明显不是最优选,那还要一个办法就是将DMA改成u8的。
修改完成,编译下载。
传输正常,问题完美解决。
我最近建了一个嵌入式的QQ交流群,感兴趣的可以进群了解一下,我会在群里分享一些常用的代码封装,以及一些项目的源码。QQ群讨论也是完全开放,只要不打广告大家可以就嵌入式尽情的沟通和交流,大家对文章中的内容有疑问也可以在群中提出,有空会尽我所能给大家一些帮助。QQ群号:643408467