本帖最后由 jinglixixi 于 2022-11-5 10:16 编辑
前面解决了开发环境的问题,捎带着回顾了一下I/O口的使用,其千万不要小看了它,在ARM中往往是用专有的I2C和SPI接口,在单片机中即使没这些,单凭一个I/O口的模拟也能把问题搞定! 这里就屏2个I/O口来实现双色OLED屏的驱动,该显示屏为0.96寸,显示分辨率为160*80,其实说到它的双色也并不彻底,也就称得上是一个准双色屏,因为它的颜色是按区域指定的,而非随心所欲地用这仅有的2种色彩,不过首行的色彩对突出标题还是很有效果的。 在实现显示驱动的过程中,整体上并没有什么难度,无非是变换了一下所使用的语句形式,这其中关键的则是对延时长短的把控。通常,主频越高,在I/O口产生状态变换时越应注意,否则会影响正常脉冲时序的生成。 经实际测试,当在模拟I2C的启动和停止函数采用如下延时值时,OLED屏是可以显示信息的。 - voidIIC_Start()
- {
- SCL = high;
- Delay(2);
- SDA = high;
- Delay(2);
- SDA = low;
- Delay(2);
- SCL = low;
- Delay(2);
- }
- voidIIC_Stop()
- {
- SCL = low;
- Delay(2);
- SDA = low;
- Delay(2);
- SCL = high;
- Delay(2);
- SDA = high;
- Delay(2);
- }
其模拟I2C发送字节数据的函数为: - voidWrite_IIC_Byte(unsigned char IIC_Byte)
- {
- unsigned char i;
- unsigned char m,da;
- da=IIC_Byte;
- SCL=0;
- Delay(2);
- for(i=0;i<8;i++)
- {
- m=da;
- m=m&0x80;
- if(m==0x80)
- {
- SDA=1;
- }
- else SDA=0;
- Delay(2);
- da=da<<1;
- SCL=1;
- Delay(2);
- SCL=0;
- Delay(2);
- }
- }
该屏的初始化函数为: - voidOLED_Init(void)
- {
- OLED_WR_Byte(0xAE,OLED_CMD);
- OLED_WR_Byte(0x02,OLED_CMD);
- OLED_WR_Byte(0x10,OLED_CMD);
- OLED_WR_Byte(0x40,OLED_CMD);
- OLED_WR_Byte(0x81,OLED_CMD);
- OLED_WR_Byte(0xff,OLED_CMD);
- OLED_WR_Byte(0xA1,OLED_CMD);
- OLED_WR_Byte(0xC8,OLED_CMD);
- OLED_WR_Byte(0xA6,OLED_CMD);
- OLED_WR_Byte(0xA8,OLED_CMD);
- OLED_WR_Byte(0x3f,OLED_CMD);
- OLED_WR_Byte(0xD3,OLED_CMD);
- OLED_WR_Byte(0x00,OLED_CMD);
- OLED_WR_Byte(0xd5,OLED_CMD);
- OLED_WR_Byte(0x80,OLED_CMD);
- OLED_WR_Byte(0xD9,OLED_CMD);
- OLED_WR_Byte(0xF1,OLED_CMD);
- OLED_WR_Byte(0xDA,OLED_CMD);
- OLED_WR_Byte(0x12,OLED_CMD);
- OLED_WR_Byte(0xDB,OLED_CMD);
- OLED_WR_Byte(0x40,OLED_CMD);
- OLED_WR_Byte(0x20,OLED_CMD);
- OLED_WR_Byte(0x02,OLED_CMD);
- OLED_WR_Byte(0x8D,OLED_CMD);
- OLED_WR_Byte(0x14,OLED_CMD);
- OLED_WR_Byte(0xA4,OLED_CMD);
- OLED_WR_Byte(0xA6,OLED_CMD);
- OLED_WR_Byte(0xAF,OLED_CMD);
- OLED_WR_Byte(0xAF,OLED_CMD);
- OLED_Clear();
- OLED_Set_Pos(0,0);
- }
这与同样尺寸的单色显示屏是存在差异的,应该加以注意。 在测试中,为了获得合适的延时值,是通过清屏函数来进行的,其内容如下: - voidOLED_Clear(void)
- {
- unsigned char i,n;
- for(i=0;i<8;i++)
- {
- OLED_WR_Byte(0xb0+i,OLED_CMD);
- OLED_WR_Byte(0x00,OLED_CMD);
- OLED_WR_Byte(0x10,OLED_CMD);
- for(n=0;n<128;n++) OLED_WR_Byte(0xf0,OLED_DATA);
- }
- }
其目的不在于清屏,而是在于获得可以观察效果的条纹,当出现图1所示的显示效果时,说明可以为它进行添加更多显示功能了。 图1 显示测试 在配备字库的情况下,其字符显示函数为: - voidOLED_ShowChar(unsigned char x,unsigned char y,unsigned char chr,unsigned char 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);
- }
- }
相应的字符串显示函数为: - voidOLED_ShowString(unsigned char x,unsigned char y,char *chr,unsigned char 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++;
- }
- }
在使用如下的主程序情况下,则可获得图2所示的显示效果。
- void main(void)
- {
- IO_Init();
- OLED_Init();
- OLED_Clear();
- OLED_ShowString(10,0,"NBK-RD8x3x",16);
- OLED_ShowString(10,2,"DB0002",16);
- OLED_ShowString(10,6,"jinglixixi",16);
- while(1)
- {
- P01=1;
- Delay(1000000);
- P01=0;
- Delay(1000000);
- }
- }
图2 显示字符串
有了OLED屏的显示功能,在串口调试的基础上就又多了一种观察调试的手段,也是开发板的功能得到了进一步的扩展和加强。
|