网络上有很多ST7789的驱动是用HAL库写的下载以后的Flash占用太大没法放足够的字库。更糟糕的是市面上很多的国产stm32f103c8t6的flash是阉割版的只有32kb。所以我第一次在我的阉割开发板上面下载HAL库的驱动时就error了。之所以用LL库写驱动是因为LL库封装更少比如LL的spi发送函数里面只有一句话把数据写入stm32的DR寄存器SPIx-DR。HAL库的spi发送代码我就不贴了很长很长。​__STATIC_INLINEvoidLL_SPI_TransmitData8(SPI_TypeDef*SPIx,uint8_tTxData){#ifdefined(__GNUC__)__IOuint8_t*spidr((__IOuint8_t*)SPIx-DR);*spidrTxData;#else*((__IOuint8_t*)SPIx-DR)TxData;#endif/* __GNUC__ */}​因为我只是改了底层SPI通信外设部分驱动ST7789的逻辑部分是一样的所以我的代码顶层封装大量沿用了这个仓库如初始化代码填充等等。学会逆向工程很重要。我的仓库我的工程是用stmcubemxkeil5开发的。这篇博客我打算讲一下LL的SPI通信和驱动ST7789的一些坑内容会不定期更新。更多ST7789的驱动可以看hhlong。​​# 奇怪的问题ST7789_WriteCommand(0xB2);// Porch control{uint8_tdata[]{0x0C,0x0C,0x00,0x33,0x33};ST7789_WriteData(data,sizeof(data));}ST7789_SetRotation(ST7789_ROTATION);// MADCTL (Display Rotation)/* Internal LCD Voltage generator settings */ST7789_WriteCommand(0XB7);// Gate ControlST7789_WriteSmallData(0x35);// Default valueST7789_WriteCommand(0xBB);// VCOM settingST7789_WriteSmallData(0x19);// 0.725v (default 0.75v for 0x20)ST7789_WriteCommand(0xC0);// LCMCTRLST7789_WriteSmallData(0x2C);// Default valueST7789_WriteCommand(0xC2);// VDV and VRH command EnableST7789_WriteSmallData(0x01);// Default valueST7789_WriteCommand(0xC3);// VRH setST7789_WriteSmallData(0x12);// -4.45v (defalut -4.1v for 0x0B)ST7789_WriteCommand(0xC4);// VDV setST7789_WriteSmallData(0x20);// Default valueST7789_WriteCommand(0xC6);// Frame rate control in normal modeST7789_WriteSmallData(0x0F);// Default value (60HZ)ST7789_WriteCommand(0xD0);// Power controlST7789_WriteSmallData(0xA4);// Default valueST7789_WriteSmallData(0xA1);// Default value/**************** Division line ****************/ST7789_WriteCommand(0xE0);{uint8_tdata[]{0xD0,0x04,0x0D,0x11,0x13,0x2B,0x3F,0x54,0x4C,0x18,0x0D,0x0B,0x1F,0x23};ST7789_WriteData(data,sizeof(data));}ST7789_WriteCommand(0xE1);{uint8_tdata[]{0xD0,0x04,0x0C,0x11,0x13,0x2C,0x3F,0x44,0x51,0x2F,0x1F,0x1F,0x20,0x23};ST7789_WriteData(data,sizeof(data));}ST7789_WriteCommand(ST7789_INVON);// Inversion ONST7789_WriteCommand(ST7789_SLPOUT);// Out of sleep modeST7789_WriteCommand(ST7789_NORON);// Normal Display onST7789_WriteCommand(ST7789_DISPON);// Main screen turned onST7789_WriteCommand(ST7789_COLMOD);// Set color modeST7789_WriteSmallData(ST7789_COLOR_MODE_16bit);HAL_Delay(50);ST7789_Fill_Color(BLACK);// Fill with Black.//backlight onST7789_BLK_Set();这是原仓库st7789的init()函数。奇怪的是只有我把set color mode的代码放到Sleepout 之后才能起作用。不然的话每次都是花屏而且只能扫描2/3的区域——我推测这是因为颜色模式被某种不可抗力从16bit改成18bit了。AI说的核心原因SLPOUT(退出睡眠) 的重置效应在旧代码中COLMOD是在复位后立即设置的此时芯片还处于Sleep In睡眠状态。ST7789 的特性很多 ST7789 芯片在执行SLPOUT(0x11) 命令时内部逻辑会进行一次微型的“软复位”以稳定电压。默认值覆盖如果在这个命令之前设置颜色模式SLPOUT过程可能会将COLMOD寄存器重置回它的硬件默认值。默认值是多少ST7789 的硬件默认颜色模式通常是18-bit (RGB666)。