工业物联网LCD数码屏的驱动原理及低功耗设计(华大半导体HC32L136)
目錄
1、驅動原理
2、驅動程序
3、低功耗設計
在工業物聯網傳感器可視化設計時,僅僅為顯示傳感器的數值變化,多選用低成本、低功耗、尺寸合適的LCD數碼屏,本次博客為各位分享華大半導體HC32L136驅動LCD數碼屏的實現方法以及低功耗設計。
1、驅動原理
LCD數碼屏本質上就是數碼管,因為其主要是為了顯示傳感器數據,多為若干個7段數碼管(7個亮段和1個小數點組成
)組成,7個亮段實際上就是7個條形的發光二極管,按順時針方向,這7個亮段分別為a、b、c、d、e、f、g大多數七段數碼管還帶有一個小數點位dp。如下圖所示:
7段數碼管中亮段的發光原理和普通的發光二極管是一樣的,所以可以把這7個亮段看成7個發光二極管,根據內部7個發光二極管的共連端不同,可將七段數碼管分為共陽(共陽極)和共陰(共陰極)兩種。共陽極就是把所有LED的陽極(正極)連接到
共同接點COM,而每個LED的陰極分別為a、b、c、d、e、f、g及dp (小數點) ;共陰極則是把所有LED的陰極(負極)連接到共同接點COM,而每個LED的陽極分別為a、b、c、d、e、f、g及dp(小數點),通過控制各個LED的亮滅來顯示數字。如下圖所示:
7段數碼管有多種顏色、多種尺寸供設計時使用,它們的顯示原理相同。如果要7段數碼管顯示數字1,只要點亮b、c兩段即可;如要顯示數字5,則需要點亮a、f、g、c、d段。其他數字和一些字母可以按照下圖中的說明點亮對應的亮段來顯示,7個亮段可以靈活地表現數字和一些字母信息。
在實際應用中,從節約端口數量、降低成本等角度考慮,LCD數碼屏中的多個數碼管并聯,采用動態掃描的方式,一位一位地輪流點亮各位顯示器(掃描),對于顯示器的每一位而言,每隔一段時間點亮一次。雖然在同一時刻只有一位顯示器在工作(點亮),但利用人眼的視覺暫留效應和發光二極管熄滅時的余輝效應,看到的卻是多個字符“同時”顯示。顯示器亮度既與點亮時的導通電流有關,也與點亮時間和間隔時間的比例有關,調整電流和時間參,可實現亮度較高較穩定的顯示。
2、驅動程序
最近在研究國產華大半導體的MCU,本次將基于HC32L136實現LCD數碼屏的驅動程序設計,這里我選用的是自定制LCD數碼屏,驅動原理和市面上的LCD屏一致,如下圖所示:
該LCD數碼屏有4個公共端,29個端口,在不借助驅動芯片的前提下,要保證MCU有29個富余的IO口,LCD數碼屏引腳對應特性如下圖所示:
?華大半導體的HC32L136支持LCD 控制器可適用于單色無源液晶顯示器(LCD)的數字控制器/驅動器,最多具有 8 個公用端子(COM)和 40 個區段端子(SEG),用以驅動 160 (4x40)或 288 (8x36)個 LCD 圖像元素。可以選擇電容分壓或電阻分壓,支持內部電阻分壓,內部電阻分壓可以調節對比度,支持 DMA 硬件數據傳輸,明顯足夠我使用了,特性如下所示:
- 高度靈活的幀速率控制。
- 支持靜態、1/2、1/3、1/4、1/6 和 1/8 占空比。
- 支持 1/2、1/3 偏置。
- 多達 16 個寄存器的 LCD 數據 RAM。
- 可通過軟件配置 LCD 的對比度。
- 3 種驅動波形生成方式:內部電阻分壓、外部電阻分壓,外部電容分壓方式,可通過軟件配置內部電阻分壓方式的功耗,從而匹配 LCD 面板所需的電容電荷。
- 支持低功耗模式:LCD 控制器可在 Active、Sleep、DeepSleep 模式下進行顯示。
- 可配置幀中斷。
- 支持 LCD 閃爍功能且可配置多種閃爍頻率
- 未使用的 LCD 區段和公共引腳可配置為數字或模擬功能。
LCD 控制器框架圖如下所示:
了解了?LCD數碼屏的特性后就要開始設計程序了~
基于HC32L136?LCD 控制器需要完成基本的配置,使用相關的API即可快速配置好掃描模式、驅動波形、幀速率等信息。
第1步:使能RCL時鐘、配置內部低速時鐘頻率為32.768kHz、開啟LCD時鐘和GPIO時鐘,配置代碼如下所示:
Sysctrl_ClkSourceEnable(SysctrlClkRCL,TRUE); ///< 使能RCL時鐘Sysctrl_SetRCLTrim(SysctrlRclFreq32768); ///< 配置內部低速時鐘頻率為32.768kHzSysctrl_SetPeripheralGate(SysctrlPeripheralLcd,TRUE); ///< 開啟LCD時鐘Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); ///< 開啟GPIO時鐘
第2步:LCD端口配置,因為是基于LCD 控制器,所以使用特定GPIO無法自定義,可參閱HC32L136管腳功能查詢及配置表進行了解。
配置代碼如下所示:
******************************************************************************** \brief 初始化外部GPIO引腳**** \return 無******************************************************************************/
void App_PortCfg(void)
{Gpio_SetAnalogMode(GpioPortA, GpioPin9); //COM1Gpio_SetAnalogMode(GpioPortA, GpioPin10); //COM2Gpio_SetAnalogMode(GpioPortA, GpioPin11); //COM3Gpio_SetAnalogMode(GpioPortA, GpioPin12); //COM4 Gpio_SetAnalogMode(GpioPortA, GpioPin8); //SEG0Gpio_SetAnalogMode(GpioPortC, GpioPin9); //SEG1Gpio_SetAnalogMode(GpioPortC, GpioPin8); //SEG2Gpio_SetAnalogMode(GpioPortC, GpioPin7); //SEG3Gpio_SetAnalogMode(GpioPortC, GpioPin6); //SEG4Gpio_SetAnalogMode(GpioPortB, GpioPin15); //SEG5Gpio_SetAnalogMode(GpioPortB, GpioPin14); //SEG6Gpio_SetAnalogMode(GpioPortB, GpioPin13); //SEG7Gpio_SetAnalogMode(GpioPortB, GpioPin12); //SEG8Gpio_SetAnalogMode(GpioPortB, GpioPin11); //SEG9Gpio_SetAnalogMode(GpioPortB, GpioPin10); //SEG10///< SEG11不用,湊成16位,方便計算Gpio_SetAnalogMode(GpioPortB, GpioPin1); //SEG12Gpio_SetAnalogMode(GpioPortB, GpioPin0); //SEG13Gpio_SetAnalogMode(GpioPortC, GpioPin5); //SEG14Gpio_SetAnalogMode(GpioPortC, GpioPin4); //SEG15Gpio_SetAnalogMode(GpioPortA, GpioPin7); //SEG16Gpio_SetAnalogMode(GpioPortA, GpioPin6); //SEG17Gpio_SetAnalogMode(GpioPortA, GpioPin5); //SEG18Gpio_SetAnalogMode(GpioPortA, GpioPin4); //SEG19Gpio_SetAnalogMode(GpioPortA, GpioPin3); //SEG20Gpio_SetAnalogMode(GpioPortA, GpioPin2); //SEG21Gpio_SetAnalogMode(GpioPortA, GpioPin1); //SEG22Gpio_SetAnalogMode(GpioPortA, GpioPin0); //SEG23Gpio_SetAnalogMode(GpioPortC, GpioPin3); //SEG24Gpio_SetAnalogMode(GpioPortC, GpioPin2); //SEG25Gpio_SetAnalogMode(GpioPortB, GpioPin3); //VLCDHGpio_SetAnalogMode(GpioPortB, GpioPin4); //VLCD3Gpio_SetAnalogMode(GpioPortB, GpioPin5); //VLCD2Gpio_SetAnalogMode(GpioPortB, GpioPin6); //VLCD1
}
第3步:配置LCD,這里我使用的是配置是:外部電容工作模式、1/4duty、1/3 BIAS、電壓泵時鐘頻率選擇2kHz、LCD掃描頻率選擇128Hz、LCD時鐘選擇RCL、選擇模式0,具體配置可查閱用戶手冊,講解的比較細致,代碼如下所示:
/********************************************************************************** \brief 配置LCD**** \return 無******************************************************************************/
void App_LcdCfg(void)
{stc_lcd_cfg_t LcdInitStruct;stc_lcd_segcom_t LcdSegCom;LcdSegCom.u32Seg0_31 = 0xFC000800; ///< 配置LCD_POEN0寄存器 開啟SEG0~SEG25,SEG12不開 ?11111100 00000000 00001000 00000000?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~COM3LcdSegCom.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 占空比(DUTY):定義為 1/(LCD 顯示器上的公用端子數)的數字LcdInitStruct.LcdBias = LcdBias3; ///< 1/3 BIAS 偏置(BIAS):驅動 LCD 時使用的電壓等級,定義為 1/(驅動 LCD 顯示的電壓等級數–1)LcdInitStruct.LcdCpClk = LcdClk2k; ///< 電壓泵時鐘頻率選擇2kHzLcdInitStruct.LcdScanClk = LcdClk128hz; ///< LCD掃描頻率選擇128HzLcdInitStruct.LcdMode = LcdMode0; ///< 選擇模式0LcdInitStruct.LcdClkSrc = LcdRCL; ///< LCD時鐘選擇RCLLcdInitStruct.LcdEn = LcdEnable; ///< 使能LCD模塊Lcd_Init(&LcdInitStruct);
}
第4步:建立LCD驅動GPIO和LCD數碼屏中數碼管之間的驅動關系,以LCD數碼屏中左上角4個數碼管為例建立(之后的數碼管顯示規律有差異)。
十六進制如下表所示:
| 數字 | 通斷控制位 | A | B | C | DP | 通斷控制位 | F | G | E | D | LCD十六進制 | ||||||
| 0 | 默認為0 | 1 | 1 | 1 | 0 | 默認為0 | 1 | 0 | 1 | 1 | 0x0E0B | ||||||
| 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0x0600 | ||||||||
| 2 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0x0C07 | ||||||||
| 3 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 0x0E05 | ||||||||
| 4 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0x060C | ||||||||
| 5 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0x0A0D | ||||||||
| 6 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0x0A0F | ||||||||
| 7 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0x0E00 | ||||||||
| 8 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0x0E0F | ||||||||
| 9 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0x0E0C | ||||||||
| DP | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0x0100 | ||||||||
| ? | 高8位 | 低8位 | 高8位 | 低8位 | ? | ||||||||||||
根據以上關系建立關系數組,該部分實現代碼如下所示:
void Lcd_Drive(int8_t id,int16_t num1,int16_t num2,int8_t point)
{///< LCD數字0~9和DP/COL1uint16_t Numerical_Tables1[11]={0x0E0B,0x0600,0x0C07,0x0E05,0x060C,0x0A0D,0x0A0F,0x0E00,0x0E0F,0x0E0C,0x0100}; uint32_t Num_Collect=0;///< 屏幕第1、2(id==0)、3、4(id==1)小數字if(id==0 || id==1){if(num1>=0 && num1<=9){Num_Collect=Numerical_Tables1[num1]; ///< 第一個數字}else if(num1==-1){Num_Collect=0x0000; ///< 熄滅}if(num2>=0 && num2<=9){Num_Collect|=Numerical_Tables1[num2]<<16; ///< 第二個數字}else if(num1==-1){Num_Collect|=0x0000<<16; ///< 熄滅}if(point==1){Num_Collect|=Numerical_Tables1[10]; ///< 第一個DP}else if(point==2){Num_Collect|=Numerical_Tables1[10]<<16; ///< 第二個DP/COL1}else if(point==3){Num_Collect|=Numerical_Tables1[10]; ///< 第一個DPNum_Collect|=Numerical_Tables1[10]<<16; ///< 第二個DP/COL1}Lcd_WriteRam(id,Num_Collect);Num_Collect=0;}
}
至此就可以實現LCD數碼屏幕的驅動。
3、低功耗設計
?HC32L136進入深度休眠狀態,不會改變端口狀態,在進入休眠前根據需要更改 IO 的狀態為休眠下的狀態,所以在深度休眠狀態下LCD數碼屏可以繼續顯示工作。
運行上述程序,LCD數碼屏所有數碼管工作點亮耗能約890毫安左右,如下圖所示:
使用低功耗設計后,耗能約為2.6微安,極大降低了功耗,如下圖所示:
低功耗設計實現代碼如下所示:
void App_LowPowerMode(void)
{///< 打開GPIO外設時鐘門控Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);//swd as gpioSysctrl_SetFunc(SysctrlSWDUseIOEn, TRUE);///< 配置為數字端口M0P_GPIO->PAADS = ~0xE000;M0P_GPIO->PBADS = ~0x0384;M0P_GPIO->PCADS = ~0xFC03;M0P_GPIO->PDADS = ~0xFFEF;///< 配置為端口輸入M0P_GPIO->PADIR = 0XFFFF;M0P_GPIO->PBDIR = 0XFFFF;M0P_GPIO->PCDIR = 0XFFFF;M0P_GPIO->PDDIR = 0XFFFF;///< 輸入下拉(除LCD端口以外)M0P_GPIO->PAPD = 0xE000;M0P_GPIO->PBPD = 0x0384;M0P_GPIO->PCPD = 0xFC03;M0P_GPIO->PDPD = 0xFFEF;Lpm_GotoDeepSleep(TRUE);
}
?
總結
以上是生活随笔為你收集整理的工业物联网LCD数码屏的驱动原理及低功耗设计(华大半导体HC32L136)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TinkerNode NB-IoT物联网
- 下一篇: 力扣(LeetCode)刷题,简单题(第