[活动专区] 【AT-START-F405测评】5.SPI驱动LCD+RTC实现电子时钟显示屏

[复制链接]
1640|0
 楼主| yuyy1989 发表于 2024-4-28 22:45 | 显示全部楼层 |阅读模式
本帖最后由 yuyy1989 于 2024-4-29 20:52 编辑

要驱动的LCD是这块
微信图片_20240428222531.jpg 微信图片_20240428222540.jpg
用到的IO口有5个,CS A0 RST MOSI SCK,其中CS A0 RST使用GPIO_output模式就行,使用AT32 Work Bench配置SPI
微信截图_20240428220304.png
使用的GPIO
微信截图_20240428220313.png
spi发送方法和LCD初始化方法
  1. YUYY_HS12864G18B_DEV_Type lcd_dev;
  2. void lcd_spiwritebyte(spi_type *spix,uint8_t byte)
  3. {
  4.     while(spi_i2s_flag_get(spix, SPI_I2S_TDBE_FLAG) == RESET);
  5.     spi_i2s_data_transmit(spix,byte);
  6. }
  7. void lcd_init()
  8. {
  9.     lcd_dev.cs.gpio = LCD_CS_GPIO_PORT;
  10.     lcd_dev.cs.pin = LCD_CS_PIN;
  11.     lcd_dev.a0.gpio = LCD_A0_GPIO_PORT;
  12.     lcd_dev.a0.pin = LCD_A0_PIN;
  13.     lcd_dev.rst.gpio = LCD_RST_GPIO_PORT;
  14.     lcd_dev.rst.pin = LCD_RST_PIN;
  15.     lcd_dev.spix = SPI1;
  16.     lcd_dev.spi_sendbyte_func = (YUYY_HS12864G18B_SpiWriteByteFunc_Type)lcd_spiwritebyte;
  17.    
  18.     YUYY_HS12864G18B_Init(&lcd_dev);
  19.     YUYY_HS12864G18B_ClearScreen(&lcd_dev);
  20.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0," AT32F405 TEST");
  21.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,2,0,"   LCD use SPI");
  22.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,4,0,"  bbs.21ic.com");
  23.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,6,0,"Code by yuyy1989");
  24.     YUYY_HS12864G18B_DisplayFinish(&lcd_dev);
  25. }
LCD驱动代码
  1. void YUYY_HS12864G18B_writebyte(YUYY_HS12864G18B_DEV_Type *hs12864_dev,uint8_t dat)
  2. {
  3.     if(hs12864_dev->spix)
  4.         hs12864_dev->spi_sendbyte_func(hs12864_dev->spix, dat);
  5. }

  6. void YUYY_HS12864G18B_cs(YUYY_HS12864G18B_DEV_Type *hs12864_dev,YUYY_GPIO_LEV_TYPE lev)
  7. {
  8.     hs12864_dev->delayus_func(5);
  9.     hs12864_dev->cs_setlev_func(&(hs12864_dev->cs),lev);
  10.     hs12864_dev->delayus_func(5);
  11. }
  12. void YUYY_HS12864G18B_rst(YUYY_HS12864G18B_DEV_Type *hs12864_dev,YUYY_GPIO_LEV_TYPE lev)
  13. {
  14.     hs12864_dev->rst_setlev_func(&(hs12864_dev->rst),lev);
  15. }
  16. void YUYY_HS12864G18B_a0(YUYY_HS12864G18B_DEV_Type *hs12864_dev,YUYY_GPIO_LEV_TYPE lev)
  17. {
  18.     hs12864_dev->a0_setlev_func(&(hs12864_dev->a0),lev);
  19. }

  20. /*
  21. * com 0指令 1数据
  22. */
  23. void YUYY_HS12864G18B_writedata(YUYY_HS12864G18B_DEV_Type *hs12864_dev,YUYY_GPIO_LEV_TYPE com,uint8_t dat)
  24. {
  25.     YUYY_HS12864G18B_cs(hs12864_dev,YUYY_GPIO_LEV0);
  26.     YUYY_HS12864G18B_a0(hs12864_dev,com);
  27.     YUYY_HS12864G18B_writebyte(hs12864_dev,dat);
  28. }

  29. void YUYY_HS12864G18B_Init(YUYY_HS12864G18B_DEV_Type *hs12864_dev)
  30. {
  31.     if(!hs12864_dev->a0_setlev_func)
  32.         hs12864_dev->a0_setlev_func = YUYY_GPIO_SetLev;
  33.     if(!hs12864_dev->cs_setlev_func)
  34.         hs12864_dev->cs_setlev_func = YUYY_GPIO_SetLev;
  35.     if(!hs12864_dev->mo_setlev_func)
  36.         hs12864_dev->mo_setlev_func = YUYY_GPIO_SetLev;
  37.     if(!hs12864_dev->rst_setlev_func)
  38.         hs12864_dev->rst_setlev_func = YUYY_GPIO_SetLev;
  39.     if(!hs12864_dev->sck_setlev_func)
  40.         hs12864_dev->sck_setlev_func = YUYY_GPIO_SetLev;
  41.     if(!hs12864_dev->delayus_func)
  42.         hs12864_dev->delayus_func = (YUYY_DELAY_Func_Type)YUYY_DelayUs;
  43.         
  44.     YUYY_HS12864G18B_cs(hs12864_dev,YUYY_GPIO_LEV0);
  45.     YUYY_HS12864G18B_rst(hs12864_dev,YUYY_GPIO_LEV0);/*低电平复位*/
  46.     hs12864_dev->delayus_func(20);
  47.     YUYY_HS12864G18B_rst(hs12864_dev,YUYY_GPIO_LEV1);/*复位完毕*/
  48.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0xE2);/*软复位*/
  49.     hs12864_dev->delayus_func(50);
  50.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0x2C); /*升压步聚 1*/
  51.     hs12864_dev->delayus_func(50);
  52.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0x2E); /*升压步聚 2*/
  53.     hs12864_dev->delayus_func(50);
  54.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0x2F); /*升压步聚 3*/
  55.     hs12864_dev->delayus_func(50);
  56.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0x24); /*0x24粗调对比度,可设置范围0x20~0x27*/
  57.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0x81); /*微调对比度*/
  58.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0x08); /*0x28,微调对比度的值,可设置范围0x00~0x3f  1f*/
  59.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0xA2); /*1/9偏压比(bias)*/
  60.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0xC8); /*行扫描顺序:从上到下*/
  61.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0xA0); /*列扫描顺序:从左到右*/
  62.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0x40); /*起始行:第一行开始*/
  63.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0xAF); /*开显示*/
  64.     YUYY_HS12864G18B_cs(hs12864_dev,YUYY_GPIO_LEV1);
  65. }

  66. void YUYY_HS12864G18B_address(YUYY_HS12864G18B_DEV_Type *hs12864_dev,uint8_t page,uint8_t column)
  67. {
  68.     YUYY_HS12864G18B_cs(hs12864_dev,YUYY_GPIO_LEV0);
  69.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,0xB0+page); //设置页地址。每页是 8行。一个画面的 64行被分成 8个页*/
  70.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,((column>>4)&0x0F)+0x10); //设置列地址的高4位
  71.     YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV0,column&0x0F); //设置列地址的低4位
  72. }

  73. /*全屏清屏*/
  74. void YUYY_HS12864G18B_ClearScreen(YUYY_HS12864G18B_DEV_Type *hs12864_dev)
  75. {
  76.     uint8_t i,j;
  77.     for(i=0;i<8;i+=1)
  78.     {
  79.         YUYY_HS12864G18B_address(hs12864_dev,i,0);
  80.         for(j=0;j<132;j+=1)
  81.         {
  82.             YUYY_HS12864G18B_writedata(hs12864_dev,YUYY_GPIO_LEV1,0x00);
  83.         }
  84.     }
  85. }

  86. /*显示8x16ASCII字符串*/
  87. void YUYY_HS12864G18B_DisplayString8x16(YUYY_HS12864G18B_DEV_Type *hs12864_dev,uint8_t option,uint8_t page,uint8_t column,char *text)
  88. {
  89.     uint8_t i=0,j;
  90.     option &= 0x01;
  91.     while(text[i]>0x00)
  92.     {
  93.         if((text[i] > 0x1F)&&(text[i] < 0x7F))
  94.         {
  95.             j=text[i]-0x20;
  96.             YUYY_HS12864G18B_DisplayDatas(hs12864_dev,option,page,column,(uint8_t *)(YUYY_FONT_ASCII_TABLE_8x16+j),8,16);
  97.             column+=8;
  98.         }
  99.         i+=1;
  100.     }
  101. }
运行效果
微信图片_20240428222545.jpg
配置RTC,设置外部低速晶振为RTC时钟源
微信截图_20240428220617.png
查看用户手册
微信截图_20240428220638.png
配置RTC
微信截图_20240429204941.png

开启唤醒中断
微信截图_20240428220832.png
在RTC初始化方法中手动使能中断
  1. void wk_ertc_init(void)
  2. {
  3.   /* add user code begin ertc_init 0 */
  4.   /* add user code end ertc_init 0 */

  5.   exint_init_type exint_init_struct;

  6.   /* add user code begin ertc_init 1 */

  7.   /* add user code end ertc_init 1 */

  8.   pwc_battery_powered_domain_access(TRUE);

  9.   crm_ertc_clock_select(CRM_ERTC_CLOCK_LEXT);
  10.   crm_ertc_clock_enable(TRUE);
  11.   ertc_reset();
  12.   ertc_wait_update();
  13.   ertc_divider_set(127, 255);
  14.   ertc_hour_mode_set(ERTC_HOUR_MODE_24);

  15.   ertc_time_set(22, 10, 0, ERTC_24H);

  16.   ertc_date_set(24, 4, 28, 7);

  17.   /* configure Wakeup timer */
  18.   ertc_wakeup_clock_set(ERTC_WAT_CLK_CK_B_16BITS);
  19.   ertc_wakeup_counter_set(0);

  20.   exint_default_para_init(&exint_init_struct);
  21.   exint_init_struct.line_enable   = TRUE;
  22.   exint_init_struct.line_mode     = EXINT_LINE_INTERRUPUT;
  23.   exint_init_struct.line_select   = EXINT_LINE_22;
  24.   exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
  25.   exint_init(&exint_init_struct);
  26.   /**
  27.    * Users need to configure this interrupt functions according to the actual application.
  28.    * 1. Call the below function to enable this  interrupt.
  29.    *      --ertc_interrupt_enable(ERTC_WAT_INT, TRUE)
  30.    * 2. Add the user's interrupt handler code into the below function in the at32f402_405_int.c file.
  31.    *      --void ERTC_WKUP_IRQHandler (void)
  32.    */

  33.   ertc_wakeup_enable(TRUE);  

  34.   /* add user code begin ertc_init 2 */
  35.     ertc_interrupt_enable(ERTC_WAT_INT,TRUE);
  36.   /* add user code end ertc_init 2 */
  37. }



中断处理
  1. char *WeekdayStr[7]= {"SUN","MON","TUE","WED","THU","FRI","SAT"};
  2. void rtc_int()
  3. {
  4.     ertc_time_type time;
  5.     char out[20];

  6.     ertc_calendar_get(&time);
  7.     sprintf(out," 20%02d-%02d-%02d %s ",time.year, time.month, time.day,WeekdayStr[time.week%7]);
  8.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0,out);
  9.     sprintf(out,"    %02d:%02d:%02d    ",time.hour, time.min, time.sec);
  10.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,2,0,out);
  11. }
  12. void ERTC_WKUP_IRQHandler(void)
  13. {
  14.   /* add user code begin ERTC_WKUP_IRQ 0 */
  15.     if(ertc_flag_get(ERTC_WATF_FLAG) != RESET)
  16.     {
  17.         ertc_flag_clear(ERTC_WATF_FLAG);
  18.         rtc_int();
  19.     }
  20.   /* add user code end ERTC_WKUP_IRQ 0 */
  21.   /* add user code begin ERTC_WKUP_IRQ 1 */

  22.   /* add user code end ERTC_WKUP_IRQ 1 */
  23. }
运行效果
WeChat_20240428222512 00_00_00-00_00_30.gif


您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部