AT32M412开发板配以内置的RTC计时器,可以轻松地实现日历的计时功能,为能直观地观察,可利用开发板上的Arduino接口来快速地实现扩展。
图1 测试结果
为简便起见,这里只通过J3来接入一个I2C接口的OLED屏,其中PA5连接OLED屏的SCK引脚,PA6连接OLED屏的SDA引脚。
图2 所用接口
对OLED显示屏所用引脚进行配置的函数为:
void oled_config()
{
gpio_init_type gpio_init_struct;
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_init_struct.gpio_pins = GPIO_PINS_5|GPIO_PINS_6;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(GPIOA, &gpio_init_struct);
}
控制所用引脚输出高低电平的语句定义为:
#define OLED_SCLK_Clr() GPIOA->clr = GPIO_PINS_5
#define OLED_SCLK_Set() GPIOA->scr = GPIO_PINS_5
#define OLED_SDIN_Clr() GPIOA->clr = GPIO_PINS_6
#define OLED_SDIN_Set() GPIOA->scr = GPIO_PINS_6
对OLED屏进行初始化的函数为:
void OLED_Init(void)
{
Write_IIC_Command(0xAE); //display off
Write_IIC_Command(0x20); //Set Memory Addressing Mode
Write_IIC_Command(0x10);
Write_IIC_Command(0xb0);//Set Page Start Address for Page Addressing Mode,0-7
Write_IIC_Command(0xc8);//Set COM Output Scan Direction
Write_IIC_Command(0x00);//---set low column address
Write_IIC_Command(0x10);//---set high column address
Write_IIC_Command(0x40);//--set start line address
Write_IIC_Command(0x81);//--set contrast control register
Write_IIC_Command(0xdf);
Write_IIC_Command(0xa1);//--set segment re-map 0 to 127
Write_IIC_Command(0xa6);//--set normal display
Write_IIC_Command(0xa8);//--set multiplex ratio(1 to 64)
Write_IIC_Command(0x3F);//
Write_IIC_Command(0xa4);//0xa4,Output follows RAM content;0xa5,Output ignores RAM content
Write_IIC_Command(0xd3);//-set display offset
Write_IIC_Command(0x00);//-not offset
Write_IIC_Command(0xd5);//--set display clock divide ratio/oscillator frequency
Write_IIC_Command(0xf0);//--set divide ratio
Write_IIC_Command(0xd9);//--set pre-charge period
Write_IIC_Command(0x22); //
Write_IIC_Command(0xda);//--set com pins hardware configuration
Write_IIC_Command(0x12);
Write_IIC_Command(0xdb);//--set vcomh
Write_IIC_Command(0x20);//0x20,0.77xVcc
Write_IIC_Command(0x8d);//--set DC-DC enable
Write_IIC_Command(0x14);//
Write_IIC_Command(0xaf);//--turn on oled panel
}
实现字符显示的函数为:
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_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);
}
}
实现RTC电子时钟功能的主程序为:
int main(void)
{
exint_init_type exint_init_struct;
ertc_time_type time;
uint32_t temp = 0;
ertc_clock_config();
system_clock_config();
nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
at32_board_init();
oled_config();
OLED_Init();
OLED_Clear();
OLED_ShowString(20,0,"AT32M412",16);
OLED_ShowString(20,2," : :",16);
OLED_ShowString(20,4," - -",16);
crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
pwc_battery_powered_domain_access(TRUE);
if (ertc_bpr_data_read(ERTC_DT1) != 0x1234)
{
ertc_config();
}
else
{
ertc_wait_update();
ertc_flag_clear(ERTC_ALAF_FLAG);
exint_flag_clear(EXINT_LINE_17);
}
exint_default_para_init(&exint_init_struct);
exint_init_struct.line_enable = TRUE;
exint_init_struct.line_mode = EXINT_LINE_INTERRUPT;
exint_init_struct.line_select = EXINT_LINE_17;
exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
exint_init(&exint_init_struct);
nvic_irq_enable(ERTCAlarm_IRQn, 0, 1);
ertc_calendar_get(&time);
OLED_ShowNum(20,4,time.year,2,16);
OLED_ShowNum(44,4,time.month,2,16);
OLED_ShowNum(68,4,time.day,2,16);
while(1)
{
ertc_calendar_get(&time);
if(temp != time.sec)
{
temp = time.sec;
OLED_ShowNum(20,2,time.hour,2,16);
OLED_ShowNum(44,2,time.min,2,16);
OLED_ShowNum(68,2,time.sec,2,16);
}
}
}
经程序的编译和下载,其测试效果如图3所示。
图3 运行效果
|
|