一直没有解决GPIO口的使用问题,现在终于解决了就可以自主设计了。 这里先实现一个I2C接口的OLED屏显示驱动,为了进行测试先在清屏函数的基础上改造了成了一个线条的显示函数,其效果如图1所示。 图1 显示线条效果
那么这个效果是如何来实现的呢? 就是以GPIO口模拟I2C的方式,其引脚与开发板的连接关系为: SCL---PC20 SDA---PC21 故使其输出高低电平的语句定义为: #defineSCL_high PORT_REGS->GROUP[2].PORT_OUT|= 1<<20 //PC20SET #defineSCL_low PORT_REGS->GROUP[2].PORT_OUT&= ~(1<<20) //PC20 CLR #defineSDA_high PORT_REGS->GROUP[2].PORT_OUT|= 1<<21 //PC21 SET #defineSDA_low PORT_REGS->GROUP[2].PORT_OUT&= ~(1<<21) //PC21 CLR 而为了是使所用的引脚工作在输出模式,则对其配置如下; PORT_REGS->GROUP[2].PORT_DIRSET= 1<<20; //PC20 OUTPUT PORT_REGS->GROUP[2].PORT_DIRSET= 1<<21; //PC21 OUTPUT 有了以上的准备工作,还要解决的一个关键问题就是延时问题,因为在引脚输出电平信号时,由于速度快会影响信号的有效控制。 比较有意思的是在其它开发板上,使用循环消耗的方式可达到延时的效果,但在这块板子上似乎不很奏效,加到3重循环也没效果。最后只好从例程所提供的延时函数下手,将ms级的延时降为us级的延时,这样才使显示屏有了显示效果。 实现以上线条显示效果的函数为: void OLED_line(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(0x0f,OLED_DATA);
}
}
其所涉及的模拟I2C方式字节数据的函数为: void Write_IIC_Byte(unsigned char IIC_Byte)
{
unsigned char i;
unsigned char m,da;
da=IIC_Byte;
SCL_low;
delay_us(5);
for(i=0;i<8;i++)
{
m=da;
m=m&0x80;
if(m==0x80)
{
SDA_high;
}
else SDA_low;
da=da<<1;
delay_us(5);
SCL_high;
delay_us(5);
SCL_low;
delay_us(5);
}
}
在实现了OLED屏的显示驱动后,就可以为它配置字符显示功能了。 在进行字符串显示函数的设计时,也有一个比较独特的现象,就是在使用指针类型时必须在前面加上const,否则无法完成编译。此外,还有一个现象就是不使用的变量不要随意定义,否则也会报错并导致无法完成编译,这比其它软件的编译处理要严格许多。
为此,字符串的显示函数被改写为: void OLED_ShowString(uint8_t x,uint8_t y,const char * 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++;
}
}
为实现图2所示的显示效果,其主程序为: int main ( void )
{
SYS_Initialize ( NULL );
SYSTICK_TimerStart();
PORT_REGS->GROUP[2].PORT_DIRSET = 1<<20;
PORT_REGS->GROUP[2].PORT_DIRSET = 1<<21;
OLED_Init();
OLED_Clear();
OLED_ShowString(20,0,"ATSAMD51 EVK",16);
OLED_ShowString(20,2,"OLED test",16);
OLED_ShowString(20,5,"jinglixixi",16);
while(1);
}
图2 字符串显示效果
这样就完整地解决了OLED屏的显示驱动问题,并实现了字符串的显示功能,再有信息显示问题就交给OLED屏了。
|