在CH32V208 开发板上配有Arduino接口,见图1所示,用它连接OLED屏与RTC计时器配合可轻松地实现电子时钟的功能。
图1 Arduino接口
- OLED屏显示驱动
这里所用的OLED屏是一款0.96寸的双色屏,该显示屏采用I2C接口工作,它与开发板的连接关系为:
SCL---PB13
SDA---PB14
所用引脚输出高低电平的语句定义为:
#define SCL_high GPIO_WriteBit(GPIOB,GPIO_Pin_13, Bit_SET)
#define SCL_low GPIO_WriteBit(GPIOB, PIO_Pin_13,it_RESET)
#define SDA_high GPIO_WriteBit(GPIOB,GPIO_Pin_14, Bit_SET)
#define SDA_low GPIO_WriteBit(GPIOB,GPIO_Pin_14, Bit_RESET)
在使用GPIO口模拟I2C的情况下,其发送字节数据的函数为:
void Write_IIC_Byte(unsigned char IIC_Byte)
{
unsigned char i;
unsigned char m,da;
da=IIC_Byte;
SCL_low;
for(i=0;i<8;i++)
{
m=da;
m=m&0x80;
if(m==0x80)
{
SDA_high;
}
else SDA_low;
da=da<<1;
SCL_high;
SCL_low;
}
}
实现OLED屏清除的函数为:
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(0x00,OLED_DATA);
}
}
实现字符显示的函数为:
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(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++)
LED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
}
}
实现数值显示的函数为:
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size2)
{
uint8_t t,temp;
uint8_t enshow=0;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
continue;
}
else enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
}
}
实现字符串显示的函数为:
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++;
}
}
实现图2所示效果的主程序为:
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
GPIO_INIT();
OLED_Init();
OLED_Clear();
OLED_ShowString(20,0,"CH32V208",16);
OLED_ShowString(20,4,"jinglixixi",16);
while(1)
{
Delay_Ms(250);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
Delay_Ms(250);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
}
}
图2 显示效果
- RTC计时
在官方的例程中提供了RTC的示例,提供RTC的初始化函数可对计时器的初始值进行设置,该函数的内容如下:
u8 RTC_Init(void)
{
u8 temp = 0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
if(BKP_ReadBackupRegister(BKP_DR1) != 0xA1A1)
{
BKP_DeInit();
RCC_LSEConfig(RCC_LSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && temp <250)
{
temp++;
Delay_Ms(20);
}
if(temp >= 250)
return 1;
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask();
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_SEC,ENABLE);
RTC_WaitForLastTask();
RTC_EnterConfigMode();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
RTC_Set(2023, 4, 18, 8, 30,00); // 更新初始计时值
RTC_ExitConfigMode();
BKP_WriteBackupRegister(BKP_DR1, 0XA1A1);
}
else
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_WakeUpPinCmd(DISABLE);
RTC_WaitForSynchro();
RTC_ITConfig(RTC_IT_SEC,ENABLE);
RTC_WaitForLastTask();
}
RTC_NVIC_Config();
RTC_Get();
return 0;
}
- 电子时钟显示
实现电子时钟功能的主程序为:
int main(void)
{
u8 i = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
GPIO_INIT();
OLED_Init();
OLED_Clear();
OLED_ShowString(28,0,"CH32V208",16);
OLED_ShowString(20,3," - -",16);
OLED_ShowString(36,5," : :",16);
RTC_Init();
while(1)
{
Delay_Ms(1000);
OLED_ShowNum(20,3,calendar.w_year,4,16);
OLED_ShowNum(60,3,calendar.w_month,2,16);
OLED_ShowNum(84,3,calendar.w_date,2,16);
OLED_ShowNum(36,5,calendar.hour,2,16);
OLED_ShowNum(60,5,calendar.min,2,16);
OLED_ShowNum(84,5,calendar.sec,2,16);
GPIO_WriteBit(GPIOA,GPIO_Pin_0, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
}
}
经编程的编译下载,其运行效果如图3所示。
图3 电子时钟显示效果