【HC32L196PCTA测评】6.LCD+WDT+RTC+FLASH测试

6.1LCD测试
HC32L196集成了LCD液晶控制模块,在这块开发板上也有一块4位段码LCD屏,接下来使用这个段码屏结合定时器做个秒表
LCD的相关IO在stkhc32l19x.h中已经被定义好了
 


初始化IO
 

复制

void lcd_io_init()

{

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);

    Gpio_SetAnalogMode(STK_LCD_COM0_PORT, STK_LCD_COM0_PIN);  //COM0

    Gpio_SetAnalogMode(STK_LCD_COM1_PORT, STK_LCD_COM1_PIN); //COM1

    Gpio_SetAnalogMode(STK_LCD_COM2_PORT, STK_LCD_COM2_PIN); //COM2

    Gpio_SetAnalogMode(STK_LCD_COM3_PORT, STK_LCD_COM3_PIN); //COM3   



    Gpio_SetAnalogMode(STK_LCD_SEG0_PORT, STK_LCD_SEG0_PIN);  //SEG0

    Gpio_SetAnalogMode(STK_LCD_SEG1_PORT, STK_LCD_SEG1_PIN);  //SEG1

    Gpio_SetAnalogMode(STK_LCD_SEG2_PORT, STK_LCD_SEG2_PIN);  //SEG2

    Gpio_SetAnalogMode(STK_LCD_SEG3_PORT, STK_LCD_SEG3_PIN);  //SEG3

    Gpio_SetAnalogMode(STK_LCD_SEG4_PORT, STK_LCD_SEG4_PIN);  //SEG4

    Gpio_SetAnalogMode(STK_LCD_SEG5_PORT, STK_LCD_SEG5_PIN); //SEG5

    Gpio_SetAnalogMode(STK_LCD_SEG6_PORT, STK_LCD_SEG6_PIN); //SEG6

    Gpio_SetAnalogMode(STK_LCD_SEG7_PORT, STK_LCD_SEG7_PIN); //SEG7

    Gpio_SetAnalogMode(GpioPortB, GpioPin3);  //VLCDH

    Gpio_SetAnalogMode(GpioPortB, GpioPin4);  //VLCD3

    Gpio_SetAnalogMode(GpioPortB, GpioPin5);  //VLCD2

    Gpio_SetAnalogMode(GpioPortB, GpioPin6);  //VLCD1

}

LCD模块使用低速时钟,因此要开启内部低速时钟或外部低速晶振
 


初始化LCD模块
 

复制

#define LCD_MODE 0

void lcd_init()

{

    stc_lcd_cfg_t LcdInitStruct;

    stc_lcd_segcom_t LcdSegCom;

    

    Sysctrl_ClkSourceEnable(SysctrlClkXTL,TRUE);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralLcd,TRUE);   ///< 开启LCD时钟



    LcdSegCom.u32Seg0_31 = 0xffffff00;                              ///< 配置LCD_POEN0寄存器 开启SEG0~SEG7

    LcdSegCom.stc_seg32_51_com0_8_t.seg32_51_com0_8 = 0xffffffff;   ///< 初始化LCD_POEN1寄存器 全部关闭输出端口

    LcdSegCom.stc_seg32_51_com0_8_t.segcom_bit.Com0_3 = 0;          ///< 使能COM0~COM3

    LcdSegCom.stc_seg32_51_com0_8_t.segcom_bit.Mux = 0;             ///< Mux=0,Seg32_35=0,BSEL=1表示:选择外部电容工作模式,内部电阻断路

    LcdSegCom.stc_seg32_51_com0_8_t.segcom_bit.Seg32_35 = 0;

    Lcd_SetSegCom(&LcdSegCom);                                      ///< LCD COMSEG端口配置



    LcdInitStruct.LcdBiasSrc = LcdExtCap;                          ///< 电容分压模式,需要外部电路配合

    LcdInitStruct.LcdDuty = LcdDuty4;                              ///< 1/4duty

    LcdInitStruct.LcdBias = LcdBias3;                              ///< 1/3 BIAS

    LcdInitStruct.LcdCpClk = LcdClk2k;                             ///< 电压泵时钟频率选择2kHz

    LcdInitStruct.LcdScanClk = LcdClk128hz;                        ///< LCD扫描频率选择128Hz

    LcdInitStruct.LcdMode = LCD_MODE==0?LcdMode0:LcdMode1;                              

    LcdInitStruct.LcdClkSrc = LcdXTL;                              ///< LCD时钟选择XTL

    LcdInitStruct.LcdEn   = LcdEnable;                             ///< 使能LCD模块

    Lcd_Init(&LcdInitStruct);

}

来看看如何显示指定的数字,先找到这块屏的资料
 


在看看手册里是怎么控制的
模式0
 


模式1
 


显示代码
 

复制

#if(LCD_MODE == 0)

uint32_t lcdrambuffer[2] = {0};

#else

uint8_t lcdrambuffer[4] = {0};

#endif

void lcdshow09num(uint8_t num,uint8_t pos)

{

    if(pos > 3)

        return;

    #if(LCD_MODE == 0)

    uint32_t temp;

    switch(num)

    {

        case 0:

            temp = 0x0F05;

            break;

        case 1:

            temp = 0x0600;

            break;

        case 2:

            temp = 0x0B06;

            break;

        case 3:

            temp = 0x0F02;

            break;

        case 4:

            temp = 0x0603;

            break;

        case 5:

            temp = 0x0D03;

            break;

        case 6:

            temp = 0x0D07;

            break;

        case 7:

            temp = 0x0700;

            break;

        case 8:

            temp = 0x0F07;

            break;

        case 9:

            temp = 0x0F03;

            break;

        default:

            break;

        

    }

    switch(pos)

    {

        case 0:

            lcdrambuffer[0] &= 0xFFFF0008;

            lcdrambuffer[0] |= temp;

            Lcd_WriteRam(0,lcdrambuffer[0]);

            break;

        case 1:

            lcdrambuffer[0] &= 0x0008FFFF;

            lcdrambuffer[0] |= ((temp<<16)&0xFFFF0000);

            Lcd_WriteRam(0,lcdrambuffer[0]);

            break;

        case 2:

            lcdrambuffer[1] &= 0xFFFF0008;

            lcdrambuffer[1] |= temp;

            Lcd_WriteRam(1,lcdrambuffer[1]);

            break;

        case 3:

            lcdrambuffer[1] &= 0x0008FFFF;

            lcdrambuffer[1] |= ((temp<<16)&0xFFFF0000);

            Lcd_WriteRam(1,lcdrambuffer[1]);

            break;

        default:

            break;

    }

    #else

    uint8_t temp[4] = {0};

    switch(num)

    {

        case 0:

            temp[0] = 0x03;

            temp[1] = 0x02;

            temp[2] = 0x03;

            temp[3] = 0x02;

            break;

        case 1:

            temp[0] = 0x00;

            temp[1] = 0x02;

            temp[2] = 0x02;

            temp[3] = 0x00;

            break;

        case 2:

            temp[0] = 0x02;

            temp[1] = 0x03;

            temp[2] = 0x01;

            temp[3] = 0x02;

            break;

        case 3:

            temp[0] = 0x02;

            temp[1] = 0x03;

            temp[2] = 0x02;

            temp[3] = 0x02;

            break;

        case 4:

            temp[0] = 0x01;

            temp[1] = 0x03;

            temp[2] = 0x02;

            temp[3] = 0x00;

            break;

        case 5:

            temp[0] = 0x03;

            temp[1] = 0x01;

            temp[2] = 0x02;

            temp[3] = 0x02;

            break;

        case 6:

            temp[0] = 0x03;

            temp[1] = 0x01;

            temp[2] = 0x03;

            temp[3] = 0x02;

            break;

        case 7:

            temp[0] = 0x02;

            temp[1] = 0x02;

            temp[2] = 0x02;

            temp[3] = 0x00;

            break;

        case 8:

            temp[0] = 0x03;

            temp[1] = 0x03;

            temp[2] = 0x03;

            temp[3] = 0x02;

            break;

        case 9:

            temp[0] = 0x03;

            temp[1] = 0x03;

            temp[2] = 0x02;

            temp[3] = 0x02;

            break;

        default:

            break;

    }

    lcdrambuffer[0] &= ~(3<<(pos*2));

    lcdrambuffer[0] |= (temp[0]<<(pos*2));

    lcdrambuffer[1] &= ~(3<<(pos*2));

    lcdrambuffer[1] |= (temp[1]<<(pos*2));

    lcdrambuffer[2] &= ~(3<<(pos*2));

    lcdrambuffer[2] |= (temp[2]<<(pos*2));

    lcdrambuffer[3] &= ~(2<<(pos*2));

    lcdrambuffer[3] |= (temp[3]<<(pos*2));

    Lcd_WriteRam(0,lcdrambuffer[0]); 

    Lcd_WriteRam(1,lcdrambuffer[1]);

    Lcd_WriteRam(2,lcdrambuffer[2]); 

    Lcd_WriteRam(3,lcdrambuffer[3]);

    #endif

}

void lcdshowdot(uint8_t dotpos,uint8_t show)

{

    if(dotpos > 3)

        return;

    #if(LCD_MODE == 0)

    switch(dotpos)

    {

        case 0:

            if(show > 0)

                lcdrambuffer[0] |= 0x00000008;

            else

                lcdrambuffer[0] &= 0xFFFFFFF7;

            Lcd_WriteRam(0,lcdrambuffer[0]);

            break;

        case 1:

            if(show > 0)

                lcdrambuffer[0] |= 0x00080000;

            else

                lcdrambuffer[0] &= 0xFFF7FFFF;

            Lcd_WriteRam(0,lcdrambuffer[0]);

            break;

        case 2:

            if(show > 0)

                lcdrambuffer[1] |= 0x00000008;

            else

                lcdrambuffer[1] &= 0xFFFFFFF7;

            Lcd_WriteRam(1,lcdrambuffer[1]);

            break;

        case 3:

            if(show > 0)

                lcdrambuffer[1] |= 0x00080000;

            else

                lcdrambuffer[1] &= 0xFFF7FFFF;

            Lcd_WriteRam(1,lcdrambuffer[1]);

            break;

        default:

            break;

    }

    #else

    if(show > 0)

        lcdrambuffer[3] |= (1<<(dotpos*2));

    else

        lcdrambuffer[3] &= ~(1<<(dotpos*2));

    Lcd_WriteRam(3,lcdrambuffer[3]);

    #endif

}

timer0修改为10ms,中断处理

复制

uint16_t timecount = 0;

uint8_t showseconddot = 1;

uint8_t timerrun = 0;

void Tim0_IRQHandler(void)

{

    //Timer0 模式0 溢出中断

    if(TRUE == Bt_GetIntFlag(TIM0, BtUevIrq))

    {

        Bt_ClearIntFlag(TIM0,BtUevIrq); //中断标志清零

        if(timerrun == 1)

        {

            if(timecount < 9999)

                timecount += 1;

            else

            {

                timecount = 0;

                //Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,!Gpio_ReadOutputIO(STK_LED_PORT, STK_LED_PIN));

            }

            lcdshow09num(timecount%10,3);

            lcdshow09num((timecount%100)/10,2);

            lcdshow09num((timecount%1000)/100,1);

            lcdshow09num(timecount/1000,0);

            if(timecount%50 == 0)

            {

                showseconddot = 1-showseconddot;

                lcdshowdot(1,showseconddot);

            }

        }

    }

}

按键处理

复制

void PortA_IRQHandler(void)

{

    if(TRUE == Gpio_GetIrqStatus(STK_USER_PORT, STK_USER_PIN))

    {            

        if(Gpio_GetInputIO(STK_USER_PORT, STK_USER_PIN) == FALSE)

        {

            if(timerrun == 0)

            {

                timecount = 0;

                showseconddot = 1;

                lcdshowdot(1,1);

                timerrun = 1;

            }

            else if(timerrun == 1)

            {

                timerrun = 2;

            }

            else

            {

                timerrun = 0;

                lcdshow09num(0,3);

                lcdshow09num(0,2);

                lcdshow09num(0,1);

                lcdshow09num(0,0);

                lcdshowdot(1,0);

            }

        }

        Gpio_ClearIrq(STK_USER_PORT, STK_USER_PIN);    

    }

}

运行效果
 



6.2WDT看门狗测试
WDT(Watch Dog Timer)看门狗定时器可用来检测和解决由软件错误引起的故障。当 WDT计数器达到设定的溢出时间后,会触发中断或产生系统复位,WDT由专用的10KHz片内振荡器驱动。
 


开启看门狗并配置好时间,看门狗复位模式
 

复制

void wdt_init()

{

    Sysctrl_SetPeripheralGate(SysctrlPeripheralWdt,TRUE);

    Wdt_Init(WdtResetEn, WdtT1s64);

    Wdt_Start();

}

LCD自动计数,在主循环中定时喂狗,按键按下阻塞住,超时后系统会复位,LCD计数从0开始

复制

int32_t main(void)

{

    xth_init();

    //时钟分频设置

    Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);

    Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);

    led_init();

    key_init();

    timer0_init();

    lcd_io_init();

    lcd_init();

    Lcd_ClearDisp();             ///< 清屏

    lcdshowdot(2,1);

    timerrun = 0;

    lcdshow09num(0,3);

    lcdshow09num(0,2);

    lcdshow09num(0,1);

    lcdshow09num(0,0);

    lcdshowdot(1,0);

    wdt_init();

    while(1)

    {

        while(Gpio_GetInputIO(STK_USER_PORT, STK_USER_PIN) == FALSE);

        Wdt_Feed();

        yuyy_delay_ms(1000);

    }

}

运行效果
 


再试试看门狗中断
 

复制

void wdt_init()

{

    Sysctrl_SetPeripheralGate(SysctrlPeripheralWdt,TRUE);

    Wdt_Init(WdtIntEn, WdtT1s64);

    EnableNvic(WDT_IRQn, IrqLevel3, TRUE);

    Wdt_Start();

}



void Wdt_IRQHandler(void)

{

    if(Wdt_GetIrqStatus())

    {

        Wdt_IrqClr();       ///<清除 wdt 中断标记

        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,!Gpio_ReadOutputIO(STK_LED_PORT, STK_LED_PIN));

    }

}

运行效果
 



6.3RTC测试
RTC(Real Time Clock)实时时钟提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自动调整
接下来开启RTC,尝试用串口打印RTC的时间,开启RTC并初始化时间
 

复制

void rtc_init()

{

    stc_rtc_initstruct_t RtcInitStruct;

    Sysctrl_SetPeripheralGate(SysctrlPeripheralRtc,TRUE);//RTC模块时钟打开

    RtcInitStruct.rtcAmpm = RtcPm;                       //24小时制

    RtcInitStruct.rtcClksrc = RtcClkXth1024;             //外部32M晶振

    RtcInitStruct.rtcPrdsel.rtcPrdsel = RtcPrdx;         //周期中断类型PRDX

    RtcInitStruct.rtcPrdsel.rtcPrdx = 1u;                //周期中断时间间隔 1秒

    RtcInitStruct.rtcTime.u8Second = 0x55;               //配置RTC时间

    RtcInitStruct.rtcTime.u8Minute = 0x01;

    RtcInitStruct.rtcTime.u8Hour   = 0x09;

    RtcInitStruct.rtcTime.u8Day    = 0x08;

    RtcInitStruct.rtcTime.u8DayOfWeek = 0x02;

    RtcInitStruct.rtcTime.u8Month  = 0x08;

    RtcInitStruct.rtcTime.u8Year   = 0x23;

    RtcInitStruct.rtcCompen = RtcCompenEnable;           // 使能时钟误差补偿

    RtcInitStruct.rtcCompValue = 0;                      //补偿值  根据实际情况进行补偿

    Rtc_Init(&RtcInitStruct);

    Rtc_AlmIeCmd(TRUE);                                  //使能闹钟中断

    

    EnableNvic(RTC_IRQn, IrqLevel3, TRUE);               //使能RTC中断向量

    Rtc_Cmd(TRUE);                                       //使能RTC开始计数

}

RTC中断处理

复制

void print_rtc()

{

    stc_rtc_time_t readtime;

    printf("RTC:%02X年%02X月%02X日 星期%02X %02X:%02X:%02X",readtime.u8Year,readtime.u8Month,readtime.u8Day,readtime.u8DayOfWeek,readtime.u8Hour,readtime.u8Minute,readtime.u8Second);

}



void Rtc_IRQHandler(void)

{

    if(Rtc_GetPridItStatus() == TRUE)

    {

        Rtc_ClearPrdfItStatus();             //清除中断标志位

        print_rtc();

    }

}

运行效果
 


串口修改时间
 

复制

void set_rtc()

{

    if(uart_rxlen > 5)

    {

        stc_rtc_time_t settime;

        settime.u8Year = uart_buffer[0];

        settime.u8Month = uart_buffer[1];

        settime.u8Day = uart_buffer[2];

        settime.u8DayOfWeek = uart_buffer[3];

        settime.u8Hour = uart_buffer[4];

        settime.u8Minute = uart_buffer[5];

        settime.u8Second = uart_buffer[6];

        Rtc_SetTime(&settime);

    }

    uart_rxlen = 0;

    uart_rxindex = 0;

}

void uart_rxtimeout()

{

    set_rtc();

}

运行效果
 


用12864LCD做一个带日期显示的电子时钟
 

复制

void time_chars_init()

{

        Spi_SetCS(M0P_SPI0, FALSE);

    yuyy_hs12864g18b_display_string_8x16(&hs12864_ctr,0,0,0,(uint8_t *)"HC32L196PCTA RTC");

    yuyy_hs12864g18b_display_string_8x16(&hs12864_ctr,0,6,0,(uint8_t *)"Code by yuyy1989");

    yuyy_hs12864g18b_display_graphic_16x16(&hs12864_ctr,0,2,16,(uint8_t *)time_chars[7]);

    yuyy_hs12864g18b_display_graphic_16x16(&hs12864_ctr,0,2,48,(uint8_t *)time_chars[8]);

    yuyy_hs12864g18b_display_graphic_16x16(&hs12864_ctr,0,2,80,(uint8_t *)time_chars[0]);

    yuyy_hs12864g18b_display_graphic_16x16(&hs12864_ctr,0,2,98,(uint8_t *)time_chars[9]);

}

void print_rtc()

{

    char out[20];

    stc_rtc_time_t readtime;

    Rtc_ReadDateTime(&readtime); 

    Spi_SetCS(M0P_SPI0, FALSE);

    sprintf(out,"%02X",readtime.u8Year);

    yuyy_hs12864g18b_display_string_8x16(&hs12864_ctr,0,2,0,(uint8_t *)out);

    sprintf(out,"%02X",readtime.u8Month);

    yuyy_hs12864g18b_display_string_8x16(&hs12864_ctr,0,2,32,(uint8_t *)out);

    sprintf(out,"%02X",readtime.u8Day);

    yuyy_hs12864g18b_display_string_8x16(&hs12864_ctr,0,2,64,(uint8_t *)out);

    yuyy_hs12864g18b_display_graphic_16x16(&hs12864_ctr,0,2,114,(uint8_t *)time_chars[readtime.u8DayOfWeek]);

    sprintf(out,"%02X:%02X:%02X",readtime.u8Hour,readtime.u8Minute,readtime.u8Second);

    yuyy_hs12864g18b_display_string_8x16(&hs12864_ctr,0,4,32,(uint8_t *)out);

    Spi_SetCS(M0P_SPI0, TRUE);

}

运行效果
 



6.4FLASH测试
HC32L196内部集成了256K的flash,每块 FLASH 按照Sector进行划分,每个Sector容量为512字节
做个简单的程序测试一下,按下按键时生成一个0-9999的随机数,用段码LCD显示并存储到FLASH,系统初始化时读出存储的数字并放到LCD上显示
 

复制

#define FLASH_ADDR 0x1FE00

void flash_init()

{

    while(Ok != Flash_Init(8, TRUE))

    {

        while(1);

    }

}



void read_data_from_flash()

{

    Flash_LockSet(FlashLock1, 0x80000000);

    while(Ok != Flash_OpModeConfig(FlashReadMode));

    testdata = *((unsigned short int *)FLASH_ADDR);

    Flash_LockAll();

    show_testdata();

}



void write_data_to_flash()

{

    Flash_LockSet(FlashLock1, 0x80000000);

    while(Ok != Flash_OpModeConfig(FlashSectorEraseMode));

    if(Ok != Flash_SectorErase(FLASH_ADDR))

    {

        while(1);

    }

    ///< FLASH 字节写、校验

    while(Ok != Flash_OpModeConfig(FlashWriteMode));

    if (Ok != Flash_Write16(FLASH_ADDR, &testdata, 1))

    {

        while(1);

    }

    Flash_LockAll();

}

按键按下生成随机数并保存

复制

void PortA_IRQHandler(void)

{

    if(TRUE == Gpio_GetIrqStatus(STK_USER_PORT, STK_USER_PIN))

    {           

        Gpio_ClearIrq(STK_USER_PORT, STK_USER_PIN);          

        if(Gpio_GetInputIO(STK_USER_PORT, STK_USER_PIN) == FALSE)

        {

            Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,!Gpio_ReadOutputIO(STK_LED_PORT, STK_LED_PIN));

            Trng_Generate();

            testdata = Trng_GetData0()%10000;

            show_testdata();

            write_data_to_flash();

        }  

    }

}

 


运行效果

---------------------
作者:yuyy1989
链接:https://bbs.21ic.com/icview-3319730-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值