我買了一個(gè)CH32V103R_NUCLEO,這個(gè)板子看起來真漂亮,黑金色。
此外,我擁有我制作的屏幕模塊。 我設(shè)計(jì)了一個(gè) Arduino 標(biāo)準(zhǔn)引腳。 事實(shí)證明,它工作良好,可以準(zhǔn)確地安裝在CH32V103R_NUCLEO板上。
此屏由ST7789驅(qū)動(dòng),具有三線9位SPI接口。 也就是說,這個(gè)屏幕沒有一個(gè)叫做D/C的引腳來區(qū)分SPI數(shù)據(jù)是reg還是command。 為此,我們需要在 SPI 發(fā)送 8 位數(shù)據(jù)之前使用單個(gè)位。 告訴屏幕接下來的 8 位是 reg 還是指令。
首先,我根據(jù)現(xiàn)有數(shù)據(jù)(在STM32平臺(tái)上,使用IO模擬SPI驅(qū)動(dòng))移植到CH32V103。 我必須感謝制造商在底層驅(qū)動(dòng)程序上所做的工作。 我的移植很簡(jiǎn)單,屏幕顯示成功。 通過一個(gè)小型的邏輯分析儀,我們可以看到一個(gè)成功的9位SPI時(shí)序。在每一個(gè)上升沿采樣MOSI引腳的電平。
這一段是程序中用來對(duì)屏幕進(jìn)行初始化所發(fā)送的數(shù)據(jù),
...... ????/*?Memory?Data?Access?Control?*/ ????LCD_WR_REG(0x36); ????LCD_WR_DATA(0x00); ? ?????/*?RGB?5-6-5-bit??*/ ????LCD_WR_REG(0x3A); ????LCD_WR_DATA(0x55); ......
到目前為止,一切都還很順利。
由于Arduino引腳中是包含SPI接口的,我在設(shè)計(jì)屏幕背板的時(shí)候特意將相應(yīng)的引腳放在特定的位置,通過觀察CH32V103R_NUCLEO的原理圖,我們可以看到制造商也將SPI2的引腳放在相應(yīng)的位置,這也就意味著我能夠使用硬件SPI來驅(qū)動(dòng)我的屏幕,這也許意味著我能夠擁有更快的刷屏速度(實(shí)話說,模擬SPI在屏幕切換時(shí)的效果太緩慢了)。
于是我做了一些工作來完成我的想法,我從開發(fā)板資料包中EVT>EXAM>SPI>1Lines_half-duplex工程中復(fù)制了一些代碼作為移植的基礎(chǔ)。
首先對(duì)SPI初始化代碼進(jìn)行修改,示例程序中沒有任何和SPI2的初始化相關(guān),我根據(jù)頭文件中的一些宏定義,修改了一些項(xiàng)目
void?SPI2_Init(void) { ????GPIO_InitTypeDef?GPIO_InitStructure; ????SPI_InitTypeDef?SPI_InitStructure; ????RCC_APB2PeriphClockCmd(?RCC_APB2Periph_GPIOB,?ENABLE?); ????GPIO_InitStructure.GPIO_Pin?=?GPIO_Pin_15|GPIO_Pin_13|GPIO_Pin_14;???? ????GPIO_InitStructure.GPIO_Mode?=?GPIO_Mode_AF_PP;????????//SPI2相關(guān)的引腳復(fù)用 ????GPIO_InitStructure.GPIO_Speed?=?GPIO_Speed_50MHz; ????GPIO_Init(?GPIOB,?&GPIO_InitStructure?); ????LCD_CTRL->BSHR=12; ????RCC_APB1PeriphClockCmd(??RCC_APB1Periph_SPI2,?ENABLE?);????//時(shí)鐘使能 ????SPI_InitStructure.SPI_Direction?=?SPI_Direction_1Line_Tx; ????SPI_InitStructure.SPI_Mode?=?SPI_Mode_Master; ????SPI_InitStructure.SPI_DataSize?=?SPI_DataSize_8b; ????SPI_InitStructure.SPI_CPOL?=?SPI_CPOL_High; ????SPI_InitStructure.SPI_CPHA?=?SPI_CPHA_2Edge;????????????//時(shí)鐘上升沿鎖定電平? ????SPI_InitStructure.SPI_NSS?=?SPI_NSS_Soft; ????SPI_InitStructure.SPI_BaudRatePrescaler?=?SPI_BaudRatePrescaler_256;????//設(shè)置速度慢一些用于調(diào)試 ????SPI_InitStructure.SPI_FirstBit?=?SPI_FirstBit_MSB; ????SPI_InitStructure.SPI_CRCPolynomial?=?7; ????SPI_Init(?SPI2,?&SPI_InitStructure?);????//SPI2的初始化 ????SPI_Cmd(?SPI2,?ENABLE?);????//SPI2使能 }
(這些修改應(yīng)該是沒有問題的,因?yàn)樵诤罄m(xù)的驗(yàn)證過程中,當(dāng)我去掉所添加的D/C發(fā)送過程后,SPI便能夠順利的發(fā)送所有的reg與command)
SPI2的發(fā)送函數(shù)如下,這段代碼從網(wǎng)絡(luò)上相關(guān)的討論中獲得,判斷了一個(gè)標(biāo)志位以及添加超時(shí)策略。
void??SPIv_WriteData(u8?Data) { ????unsigned?int?retry=0; ????while(SPI_I2S_GetFlagStatus(SPI2,?SPI_I2S_FLAG_TXE)==RESET) ????{ ????????retry++; ????????if(retry>1000) ????????????{ ????????????????printf("timeout!\r\n"); ????????????????break; ????????????} ????} ????SPI_I2S_SendData(SPI2,Data); ????retry=0; }
接下來我開始嘗試在SPI發(fā)送前添加一個(gè)bit來當(dāng)作D/C位,發(fā)送程序如下
void?LCD_WR_REG(u8?data) {? ????LCD_CS_CLR; ????IO_SW(0);????//用于切換SCLK和MOSI引腳的工作模式 ????SPI_MOSI_CLR;????//發(fā)送REG時(shí)D/C為0,發(fā)送COMMAND時(shí)D/C為1 ????SPI_SCLK_CLR; ????Delay_Us(2); ????SPI_SCLK_SET; ????IO_SW(1);????//用于切換SCLK和MOSI引腳的工作模式 ????SPIv_WriteData(data); ????LCD_CS_SET; }
上述的工作模式切換部分是我通過在一些論壇搜索時(shí)得到的提示,在直接操作SCLK和MOSI引腳之前將其初始化為out_PP,在操作完成之后將其恢復(fù)AF_PP。這個(gè)函數(shù)如下所示
void?IO_SW(uint8_t?flag) { ????GPIO_InitTypeDef?iosw; ????iosw.GPIO_Pin?=?GPIO_Pin_13|GPIO_Pin_15; ????(flag==0)?(iosw.GPIO_Mode?=?GPIO_Mode_Out_PP):?(iosw.GPIO_Mode?=?GPIO_Mode_AF_PP); ????iosw.GPIO_Speed?=?GPIO_Speed_50MHz; ????GPIO_Init(GPIOB,?&iosw); }
至此,我感覺移植工作應(yīng)該已經(jīng)完成了,從我個(gè)人有限的知識(shí)來看,我的工作完成的很不錯(cuò),很周到,但是事實(shí)卻很糟糕,我的屏幕沒有顯示任何東西,通過邏輯分析儀我能夠看到,我好像離成功已經(jīng)非常近了(下方紅字表示正確的),存在一些問題,我單獨(dú)操作的MOSI電平似乎延后到了硬件SPI的發(fā)送動(dòng)作中,此外還有操作MOSI不成功的情況,但是現(xiàn)在我卻不知道如何進(jìn)行下一步了,我需要開始尋求大家的幫助。
我也曾試著在發(fā)送函數(shù)的不同位置添加延時(shí),但那看起來似乎沒有起作用。
希望有一些朋友有相關(guān)經(jīng)驗(yàn)的能夠一起討論