- void RTC_Configure(void)
- {
- NVIC_InitTypeDef NVIC_InitStruct;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_RTC | RCC_APB1Periph_BKP, ENABLE);
- PWR_BackupAccessCmd(ENABLE);
- BKP_DeInit();
- if (BKP_ReadBackupRegister(BKP_DR1) != 0x5B5B)
- {
- RCC_LSEConfig(RCC_LSE_ON);
- while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
- {
- }
- RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
- RCC_RTCCLKCmd(ENABLE);
- RTC_WaitForSynchro();
- RTC_WaitForLastTask();
- RTC_ITConfig(RTC_IT_SEC, ENABLE);
- RTC_WaitForLastTask();
- RTC_SetPrescaler(32767);
- RTC_WaitForLastTask();
- printf("\r\n%s", __FUNCTION__);
- BKP_WriteBackupRegister(BKP_DR1, 0x5B5B);
- }
- else
- {
- printf("\r\nNeed't to configure RTC.");
- RTC_WaitForSynchro();
- RTC_ITConfig(RTC_IT_SEC, ENABLE);
- RTC_WaitForLastTask();
- }
- NVIC_InitStruct.NVIC_IRQChannel = RTC_BKP_IRQn;
- NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
- NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStruct);
- RTC_LoadDefault();
- }
2、RTC_BKP_IRQHandler中断处理
RTC(实时时钟)和 BKP(备份寄存器)共用的中断源
实际上包含多个可能的中断事件,主要分:
秒中断(RTC_IT_SEC)
闹钟中断(RTC_IT_ALR)
溢出中断(RTC_IT_OW)
本例中,用于更新时间显示RTC_UpdateCalendar
打印时间RTC_PrintDateTime
- void RTC_BKP_IRQHandler(void)
- {
- if (RESET != RTC_GetITStatus(RTC_IT_SEC))
- {
- RTC_UpdateCalendar();
- RTC_PrintDateTime();
- RTC_ClearITPendingBit(RTC_IT_SEC);
- RTC_WaitForLastTask();
- }
- }
3、RTC_UpdateCalendar()更新时间
- void RTC_UpdateCalendar(void)
- {
- static uint32_t PreTotalDay = 0;
- uint32_t TotalSecond = 0;
- uint32_t TotalDay = 0;
- uint16_t Year = 1970;
- uint8_t Month = 0;
- TotalSecond = RTC_GetCounter();
- TotalDay = TotalSecond / 86400;
- if (PreTotalDay != TotalDay)
- {
- PreTotalDay = TotalDay;
- while (TotalDay >= 365)
- {
- if (RTC_LeapYear(Year) == 1)
- {
- if (TotalDay >= 366)
- {
- TotalDay -= 366;
- }
- else
- {
- break;
- }
- }
- else
- {
- TotalDay -= 365;
- }
- Year++;
- }
- RTC_Calendar.year = Year;
- while (TotalDay >= 28)
- {
- if ((Month == 1) && (RTC_LeapYear(RTC_Calendar.year) == 1))
- {
- if (TotalDay >= 29)
- {
- TotalDay -= 29;
- }
- else
- {
- break;
- }
- }
- else
- {
- if (TotalDay >= RTC_DayOfMonth[Month])
- {
- TotalDay -= RTC_DayOfMonth[Month];
- }
- else
- {
- break;
- }
- }
- Month++;
- }
- RTC_Calendar.month = Month + 1;
- RTC_Calendar.day = TotalDay + 1;
- RTC_Calendar.week = RTC_GetWeek(RTC_Calendar.year, RTC_Calendar.month, RTC_Calendar.day);
- }
- RTC_Calendar.hour = (TotalSecond % 86400) / 3600;
- RTC_Calendar.minute = ((TotalSecond % 86400) % 3600) / 60;
- RTC_Calendar.second = ((TotalSecond % 86400) % 3600) % 60;
- }
4、RTC_PrintDateTime打印时间
- void RTC_PrintDateTime(void)
- {
- printf("\r\n%04d-%02d-%02d", RTC_Calendar.year, RTC_Calendar.month, RTC_Calendar.day);
- switch (RTC_Calendar.week)
- {
- case 0:
- printf(" SUN ");
- break;
- case 1:
- printf(" MON ");
- break;
- case 2:
- printf(" TUE ");
- break;
- case 3:
- printf(" WED ");
- break;
- case 4:
- printf(" THU ");
- break;
- case 5:
- printf(" FRI ");
- break;
- case 6:
- printf(" SAT ");
- break;
- default:
- break;
- }
- printf("%02d:%02d:%02d\r\n", RTC_Calendar.hour, RTC_Calendar.minute, RTC_Calendar.second);
-
-
-
- }
5、增加自己的时间显示
因为用到74hc595驱动点阵屏,74hc595没有输出锁定功能,需要将相关的点阵屏驱动放在while(1)中不断刷新。
- void RTC_Calendar_Sample(void)
- {
- printf("\r\nTest %s", __FUNCTION__);
- //初始化LED点阵屏
- config_led_matrix_gpio();
-
- //配置RTC
- RTC_Configure();
- while (1)
- {
- //PLATFORM_LED_Toggle(LED1);
- //PLATFORM_DelayMS(100);
-
- //在LED点阵屏上显示
- clear_screen();
- vs_clear_screen();
-
- //填充小时
- fill_num_to_buffer(0,0,RTC_Calendar.hour/10);
- fill_num_to_buffer(4,0,RTC_Calendar.hour%10);
- //填充:
- fill_num_to_buffer(8,0,10);
- //填充小时
- fill_num_to_buffer(12,0,RTC_Calendar.minute/10);
- fill_num_to_buffer(16,0,RTC_Calendar.minute%10);
- //填充:
- fill_num_to_buffer(20,0,10);
- //填充秒钟
- fill_num_to_buffer(24,0,RTC_Calendar.second/10);
- fill_num_to_buffer(28,0,RTC_Calendar.second%10);
-
- vs_render_screen();
- render_screen_to_matrix8x24();
- }
- }
6、点阵屏的驱动
- #include "hc595.h"
- #include "hal_conf.h"
- //位置,595扫描的行/列
- //COM
- const uint8_t pos[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
- //显示缓存 7*11*4=7*44,使用8*48缓存
- //SEG,实际屏幕,节约空间
- uint8_t matrix3[48]={0x00};
- // 虚拟屏幕
- uint8_t virtual_screen[SCREEN_WIDTH][SCREEN_HEIGHT]={0};
- unsigned char bigNUM[]=
- {
- /* 3*7数字字模,上下顶到头,空左边一列*/
- 0x07,0x05,0x05,0x05,0x05,0x05,0x07, /*0*/
- 0x02,0x02,0x02,0x02,0x02,0x02,0x02, /*1*/
- 0x07,0x01,0x01,0x07,0x04,0x04,0x07, /*2*/
- 0x07,0x01,0x01,0x07,0x01,0x01,0x07, /*3*/
- 0x05,0x05,0x05,0x07,0x01,0x01,0x01, /*4*/
- 0x07,0x04,0x04,0x07,0x01,0x01,0x07, /*5*/
- 0x07,0x04,0x04,0x07,0x05,0x05,0x07, /*6*/
- 0x07,0x01,0x01,0x01,0x01,0x01,0x01, /*7*/
- 0x07,0x05,0x05,0x07,0x05,0x05,0x07, /*8*/
- 0x07,0x05,0x05,0x07,0x01,0x01,0x07, /*9*/
- 0x00,0x02,0x00,0x00,0x00,0x02,0x00, /*:*/
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*空,补位*/
- };
- unsigned char smallNUM[]=
- {
- /* 4*7数字字模,上下各空一行,空左边一列*/
- 0x00,0x07,0x05,0x05,0x05,0x07,0x00, /*0*/
- 0x00,0x02,0x02,0x02,0x02,0x02,0x00, /*1*/
- 0x00,0x07,0x01,0x07,0x04,0x07,0x00, /*2*/
- 0x00,0x07,0x01,0x07,0x01,0x07,0x00, /*3*/
- 0x00,0x05,0x05,0x07,0x01,0x01,0x00, /*4*/
- 0x00,0x07,0x04,0x07,0x01,0x07,0x00, /*5*/
- 0x00,0x07,0x04,0x07,0x05,0x07,0x00, /*6*/
- 0x00,0x07,0x01,0x01,0x01,0x01,0x00, /*7*/
- 0x00,0x07,0x05,0x07,0x05,0x07,0x00, /*8*/
- 0x00,0x07,0x05,0x07,0x01,0x07,0x00, /*9*/
- 0x00,0x00,0x02,0x00,0x02,0x00,0x00, /*:*/
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*空,补位*/
- };
- void config_led_matrix_gpio(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
- RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOD, ENABLE);
- GPIO_StructInit(&GPIO_InitStruct);
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_11 | GPIO_Pin_15;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(GPIOA, &GPIO_InitStruct);
-
- GPIO_StructInit(&GPIO_InitStruct);
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(GPIOD, &GPIO_InitStruct);
-
- LED_OE_CLR;
- }
- /*
- * PN:反显
- * */
- void HC595(uint8_t c,uint8_t PN)
- {
- uint8_t i;
- for(i=0;i<8;i++){
- if(PN==0){ //正常显示
- if((c>>i) & 0x01) LED_SER_SET;
- else LED_SER_CLR;
- }
- else{ //反显
- if((c>>i) & 0x01) LED_SER_CLR;
- else LED_SER_SET;
- }
- LED_SRCK_CLR;
- LED_SRCK_SET; // 上升沿进行一次数据移入
- }
- }
- void clear_screen(void)
- {
- uint8_t i;
- for ( i = 0; i < 48; i++) {
- matrix3[i]=0x00;
- }
- }
- //紧凑缓存画点
- void draw_pixel(uint8_t x,uint8_t y)
- {
- uint8_t mx,my;
- if (x>21) x=x+2;
- mx=5-x/8;
- my=y+1;
- matrix3[mx*8+my]|=1<<(7-x%8);
- }
- //控制闪烁的措施,如果点灯少就多循环显示,否则少循环显示
- uint8_t count_ones(uint8_t i) {
- uint8_t count = 0;
- while (i != 0) {
- i &= (i - 1); // 清除最低位的1
- count++;
- }
- return count;
- }
- //将紧凑缓存内容显示在LED矩阵上,没有虚拟屏直接显示的函数
- //pBuff通常是matrix3,
- void render_screen_to_matrix8x24(void)
- {
- uint8_t *pBuff=matrix3;
- uint8_t k;
- uint16_t m,n;
- for(m=0;m<32*2;m++) //为移动预留
- {
- for(k=0;k<7;k++) //行扫描
- {
- for(n=0;n<(count_ones(pBuff[k])+count_ones(pBuff[k+8])+count_ones(pBuff[k+16])+count_ones(pBuff[k+24])
- +count_ones(pBuff[k+32])+count_ones(pBuff[k+40]))*2;n++)//控制显示速度,防止闪烁
-
- {
- HC595(~pos[k],0);
- HC595(pBuff[k],0);
- HC595(pBuff[k+8],0);
- HC595(pBuff[k+16],0);
- HC595(~pos[k],0);
- HC595(pBuff[k+24],0);
- HC595(pBuff[k+32],0);
- HC595(pBuff[k+40],0);
- LED_RCK_CLR;
- LED_RCK_SET; //并行输出
- __nop();__nop();
-
- }
- }
- }
- //传COM -
- //传SEG +
- }
- //虚拟屏清屏
- void vs_clear_screen(void)
- {
- uint8_t x,y;
- for ( y = 0; y < SCREEN_HEIGHT; y++) {
- for ( x = 0; x < SCREEN_WIDTH; x++) {
- virtual_screen[x][y] = 0;
- }
- }
- }
- //虚拟屏画点
- void vs_drawpixel(uint8_t x,uint8_t y)
- {
- virtual_screen[x][y]=1;
- }
- void vs_clearpixel(uint8_t x,uint8_t y)
- {
- virtual_screen[x][y]=0;
- }
- //虚拟屏复制到紧凑缓存
- void vs_render_screen(void)
- {
- uint8_t x,y;
- //clear_screen();
- for ( y = 0; y < SCREEN_HEIGHT; y++) {
- for ( x = 0; x < SCREEN_WIDTH; x++) {
- if (virtual_screen[x][y]) {
- draw_pixel(x, y); // 画点
- } else {
- // 如果需要清除点,可以调用清屏函数或设置背景色
- }
- }
- }
- }
- /*
- * 填充数字到屏幕位置,写物理和虚拟缓存
- * (x,y)是显示位置坐标;NUM是要显示的数字
- */
- void fill_num_to_buffer(uint8_t x,uint8_t y,uint8_t num)
- {
- uint8_t i,j;
- for(i=0;i<7;i++)
- {
- for(j=0;j<4;j++)
- {
- if(((smallNUM[num*7+i]>>j)&0x01)==0x01)
- {
- //draw_pixel(x+4-j, y+i);
- vs_drawpixel(x+4-j, y+i);
- }
- else
- {
- vs_clearpixel(x+4-j, y+i);
- }
- }
- }
- }
- void hc595_test(void)
- {
- config_led_matrix_gpio();
-
-
- while(1)
- {
- vs_clear_screen();
- fill_num_to_buffer(0,0,0);
- fill_num_to_buffer(4,0,1);
- fill_num_to_buffer(8,0,2);
- fill_num_to_buffer(12,0,3);
- fill_num_to_buffer(16,0,4);
- fill_num_to_buffer(20,0,5);
- fill_num_to_buffer(24,0,6);
- fill_num_to_buffer(28,0,7);
- fill_num_to_buffer(32,0,8);
- fill_num_to_buffer(36,0,9);
-
- vs_render_screen();
- render_screen_to_matrix8x24();
- }
- }
6、效果