CH32V307开发板是一款评估板,故其外设的配置较为简单,要想丰富自己的外设资源,可通过扩展接口来实现。
作为人机交互的重要桥梁,显示功能是不可或缺的,否则只能靠串口来观察结果,这会感到十分的不便。
这里选用的显示器件是一款I2C接口的双色OLED屏,可直接与扩展接口相连接。
为便于插接使用,OLED屏与开发板的连接关系为:
CLK---PB13
DIN---PB14
由于是初次以RT-Thread Studio在CH32V307上驱动OLED屏显示,这里是直接使用所掌握的GPIO口用法,以软件模拟的方式来驱动OLED屏显示。
完成,对2个引脚输出高低电平的语句设置为:
#define OLED_SCLK_Set() GPIO_WriteBit(GPIOB, GPIO_Pin_13, Bit_SET)
#define OLED_SCLK_Clr() GPIO_WriteBit(GPIOB, GPIO_Pin_13, Bit_RESET)
#define OLED_SDIN_Set() GPIO_WriteBit(GPIOB,GPIO_Pin_14, Bit_SET)
#define OLED_SDIN_Clr() GPIO_WriteBit(GPIOB, GPIO_Pin_14, Bit_RESET)
对OLED屏所用引脚的配置函数:
void app_OLED_Init(void){ GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); }
复制代码以软件方式模拟字节数据发送的函数为:
void Write_IIC_Byte(unsigned char IIC_Byte){ unsigned char i; unsigned char m,da; da=IIC_Byte; OLED_SCLK_Clr(); for(i=0;i<8;i++) { m=da; m=m&0x80; if(m==0x80) { OLED_SDIN_Set(); } else OLED_SDIN_Clr(); Delay_Us1(2); da=da<<1; OLED_SCLK_Set(); Delay_Us1(2); OLED_SCLK_Clr(); Delay_Us1(2); } }
复制代码由于CH32V307的主频速度比较高,为此在控制GPIO口输出高低电平信号时,需加相应的延时以保证信号的可靠的产生作用。
以字节数据模拟发送为基础,实现字符显示的函数为:
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size){ unsigned char c=0,i=0; c=chr-' '; if(x>Max_Column-1) { x=0; y=y+2; } if(Char_Size ==16) { OLED_Set_Pos(x,y); for(i=0;i<8;i++) OLED_WR_Byte(F8X16[c*16+i],OLED_DATA); OLED_Set_Pos(x,y+1); for(i=0;i<8;i++) OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA); } else { OLED_Set_Pos(x,y); for(i=0;i<6;i++) OLED_WR_Byte(F6x8[c][i],OLED_DATA); } }
复制代码以字符显示函数为依托,字符串显示函数的内容为:
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size){ unsigned char j=0; while (chr[j]!='\0') { OLED_ShowChar(x,y,chr[j],Char_Size); x+=8; if(x>120) { x=0; y+=2; } j++; } }
复制代码在汉字库的支持下,实现汉字显示的函数为:
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no){ uint8_t t,adder=0; OLED_Set_Pos(x,y); for(t=0;t<16;t++) { OLED_WR_Byte(Hzk[2*no][t],OLED_DATA); adder+=1; } OLED_Set_Pos(x,y+1); for(t=0;t<16;t++) { OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA); adder+=1; } }
复制代码有了以上函数的支持,通过主程序的设计就可实现图1和图2的显示显示,其相应的主程序为:
int main(void){ rt_kprintf("MCU: CH32V307\n"); rt_kprintf("SysClk: %dHz\n",SystemCoreClock); rt_kprintf("www.wch.cn\n"); LED1_BLINK_INIT(); LED2_BLINK_INIT(); GPIO_ResetBits(GPIOA,GPIO_Pin_0); app_OLED_Init(); OLED_Init(); OLED_Clear(); OLED_ShowString(0,0,"CH32V307 TEST",16); OLED_ShowString(0,2,"OLED Display",16); OLED_ShowCHinese(0,4,0); OLED_ShowCHinese(20,4,1); OLED_ShowCHinese(40,4,2); OLED_ShowCHinese(60,4,3); OLED_ShowCHinese(80,4,4); OLED_ShowCHinese(100,4,5); OLED_ShowCHinese(30,6,6); OLED_ShowCHinese(50,6,7); OLED_ShowCHinese(70,6,8); while(1) { GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET); rt_thread_mdelay(500); GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET); rt_thread_mdelay(500); } }
复制代码经程序的编译下载,即可观察到预期的效果。
图1 显示字符效果
图2显示中文效果
通过OLED屏驱动功能的实现,既得到了预期的设计目标,有巩固了对GPIO口的掌握,可谓是一举多得。