先前受困于没有解决GPIO引脚正确输出高低电平的问题,故难以完成串行数码管显示模块的驱动,如今解决了GPIO的输出问题,自然就可以直面显示驱动啦。
由于该显示模块以MAX7219为主控芯片,可显示8位数值,并支持级联使用,故显示数位可进行相应的扩展。在使用时,除电源外它只需3个GPIO口,就可对其进行扩展,因此十分节省引脚资源。

图1 串行数码管显示模块
该显示模块与开发板的连接关系为:
SCL---PIN_62
SDA---PIN_61
CS---PIN_57
为此在 VE文件中建立的映射关系如下:
GPIO5_0 PIN_62 #CLK
GPIO5_1 PIN_61 #SDA
GPIO5_4 PIN_57 #CS
为便于向串行数码管显示模块提供高低电平的输出,所定义的语句为:
#define CLK_SetLow GPIO_SetLow(GPIO5,GPIO_BIT0)
#define CLK_SetHigh GPIO_SetHigh(GPIO5,GPIO_BIT0)
#define DIN_SetLow GPIO_SetLow(GPIO5,GPIO_BIT1)
#define DIN_SetHigh GPIO_SetHigh(GPIO5,GPIO_BIT1)
#define CS_SetLow GPIO_SetLow(GPIO5,GPIO_BIT4)
#define CS_SetHigh GPIO_SetHigh(GPIO5,GPIO_BIT4)
由于该串行数码管显示模块所使用的关键芯片为MAX7219,故为它配置了一个串行发送字节数据的函数,其内容为:
void Write_Max7219_byte(char DATA)
{
char i;
CS_SetLow;
UTIL_IdleUs(10);
for(i=8;i>=1;i--)
{
CLK_SetLow;
if(DATA&0x80)
DIN_SetHigh;
else
DIN_SetLow;
UTIL_IdleUs(10);
DATA=(char)(DATA<<1);
CLK_SetHigh;
UTIL_IdleUs(10);
}
}以函数Write_Max7219_byte()为基础,向指定地址发送数据的函数为:
void Write_Max7219(char address,char dat)
{
CS_SetLow;
Write_Max7219_byte(address);
Write_Max7219_byte(dat);
CS_SetHigh;
}对于串行数码管显示模块,其初始化函数为:
void Init_MAX7219(void)
{
Write_Max7219(0x09, 0xff);
Write_Max7219(0x0a, 0x02);
Write_Max7219(0x0b, 0x07);
Write_Max7219(0x0c, 0x01);
Write_Max7219(0x0f, 0x00);
}要实现串行数码管显示模块的驱动,相应的测试程序为:
void TestGpio()
{
SYS_EnableAPBClock(APB_MASK_GPIO5);
GPIO_SetOutput(GPIO5, GPIO_BIT0);
GPIO_SetOutput(GPIO5, GPIO_BIT1);
GPIO_SetOutput(GPIO5, GPIO_BIT4);
GPIO_SetLow(GPIO5,GPIO_BIT0);
GPIO_SetLow(GPIO5,GPIO_BIT1);
GPIO_SetLow(GPIO5,GPIO_BIT4);
Init_MAX7219();
Write_Max7219(1,1);
Write_Max7219(2,2);
Write_Max7219(3,3);
Write_Max7219(4,4);
Write_Max7219(5,5);
Write_Max7219(6,6);
Write_Max7219(7,7);
Write_Max7219(8,8);
while (1);
}经程序编译与烧录,其效果如图2所示。

图2 显示效果图
解决了串行数码管的显示问题,就确定了模拟驱动方式的成功,接下来就可以模拟I2C的方式来驱动OLED显示屏了。
这里选配的是一款0.96寸的单色显示屏,以匹配AG32VH407开发板的小体型。
OLED屏与开发板的连接关系为:
SCL---PIN_62
SDA---PIN_61
为此在 VE文件中建立的映射关系如下:
GPIO5_0 PIN_62 #CLK
GPIO5_1 PIN_61 #SDA
为便于向串行数码管显示模块提供高低电平的输出,所定义的语句为:
#define CLK_SetLow GPIO_SetLow(GPIO5,GPIO_BIT0)
#define CLK_SetHigh GPIO_SetHigh(GPIO5,GPIO_BIT0)
#define DIN_SetLow GPIO_SetLow(GPIO5,GPIO_BIT1)
#define DIN_SetHigh GPIO_SetHigh(GPIO5,GPIO_BIT1)
模拟I2C方式工作的辅助函数为:
void IIC_Start()
{
CLK_SetHigh;
UTIL_IdleUs(3);
DIN_SetHigh;
UTIL_IdleUs(3);
DIN_SetLow;
UTIL_IdleUs(3);
CLK_SetLow;
UTIL_IdleUs(3);
}
void IIC_Stop()
{
CLK_SetHigh;
UTIL_IdleUs(3);
DIN_SetLow;
UTIL_IdleUs(3);
DIN_SetHigh;
UTIL_IdleUs(3);
}
void IIC_Wait_Ack()
{
CLK_SetHigh;
UTIL_IdleUs(3);
CLK_SetLow;
UTIL_IdleUs(3);
}模拟I2C方式发送字节数据的函数为:
void Write_IIC_Byte(unsigned char IIC_Byte)
{
unsigned char i;
unsigned char m,da;
da=IIC_Byte;
CLK_SetLow;
for(i=0;i<8;i++)
{
m=da;
m=m&0x80;
if(m==0x80)
{
DIN_SetHigh;
}
else
DIN_SetLow;
da=da<<1;
UTIL_IdleUs(3);
CLK_SetHigh;
UTIL_IdleUs(3);
CLK_SetLow;
UTIL_IdleUs(3);
}
}清屏函数的内容为:
void OLED_Clear(void)
{
uint8_t 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(0x0,OLED_DATA);
}
}OLED屏的初始化函数为:
void OLED_Init(void)
{
Write_IIC_Command(0xAE);
Write_IIC_Command(0x20);
Write_IIC_Command(0x10);
Write_IIC_Command(0xb0);
Write_IIC_Command(0xc8);
Write_IIC_Command(0x00);
Write_IIC_Command(0x10);
Write_IIC_Command(0x40);
Write_IIC_Command(0x81);
Write_IIC_Command(0xdf);
Write_IIC_Command(0xa1);
Write_IIC_Command(0xa6);
Write_IIC_Command(0xa8);
Write_IIC_Command(0x3F);
Write_IIC_Command(0xa4);
Write_IIC_Command(0xd3);
Write_IIC_Command(0x00);
Write_IIC_Command(0xd5);
Write_IIC_Command(0xf0);
Write_IIC_Command(0xd9);
Write_IIC_Command(0x22);
Write_IIC_Command(0xda);
Write_IIC_Command(0x12);
Write_IIC_Command(0xdb);
Write_IIC_Command(0x20);
Write_IIC_Command(0x8d);
Write_IIC_Command(0x14);
Write_IIC_Command(0xaf);
}字符串的显示函数为:
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;
}
}实现驱动测试的主程序为:
int main(void)
{
board_init();
SYS_EnableAPBClock(APB_MASK_GPIO5);
GPIO_SetOutput(GPIO5, GPIO_BIT0);
GPIO_SetOutput(GPIO5, GPIO_BIT1);
GPIO_SetOutput(GPIO5, GPIO_BIT4);
GPIO_SetLow(GPIO5,GPIO_BIT0);
GPIO_SetLow(GPIO5,GPIO_BIT1);
GPIO_SetLow(GPIO5,GPIO_BIT4);
OLED_Init();
OLED_Clear();
OLED_ShowString(0,0," HELLO WORLD ! ",16);
OLED_ShowString(0,2," ",16);
OLED_ShowCHinese(8,2,0);
OLED_ShowCHinese(24,2,1);
while (1);
}经程序的编译和下载,其测试效果如图3所示。

图3 测试效果

我要赚赏金
