STM32F103学习笔记(4)——LCD段码屏HT1621使用
一、簡介
HT1621 是 128 點 內存映象和多功能的 LCD 驅動器 HT1621 的軟件配置特性使它適用于多種 LCD 應用場合包括 LCD 模塊和顯示子系統。用于連接主控制器和 HT1621 的管腳只有 4 或 5 條 HT1621,還有一個節電命令用于降低系統功耗。
二、字符顯示原理
液晶管點亮和熄滅原理分別為在對應的RAM地址中寫1和寫0。 首先需要清楚所驅動控制的液晶的COM-SEG對應關系,然后需要了解HT1621的32×4RAM地址映射。
例如要控制的液晶的裝腳成品圖部分如下:
著重看一個液晶數碼管,我們了解原理就行。可以看到圖3中是第2個液晶數碼管,有7段,分別為A,B,C,D,E,F,G。也就分別為下面COM\SEG地址對應關系圖中的2A,2B,2C,2D,2E,2F,2G。
液晶的顯示字符的部分COM公共端輸出口和SEG段輸出口的分布如下表所示,同理我們可以看到例如:2D對應(SEG5,COM0),2E對應(SEG5,COM1),2F對應(SEG5,COM2),2A對應(SEG5,COM3),2C對應(SEG4,COM1),2G對應(SEG4,COM2),2B對應(SEG4,COM3)。
HT1621的RAM 地址映射如下圖所示:
可以清楚的看到要控制液晶段對應SEG號作為6位地址,COM號對應作為4位數據寫入,此時注意4位數據的高低位。寫數據到RAM命令格式為:101+6位RAM地址+4位數據,其中RAM地址為SEG序號。
例如我們在圖3的第二個液晶數碼管上顯示數字,首先我們根據圖3得到地址映射關系,先寫入地址SEG4中的四位數據(COM3,COM2,COM1,COM0),再寫如地址SEG5中的四位數據(COM3,COM2,COM1,COM0),對應關系如下:
所以如果在圖3中顯示“5”,則在顯示的液晶段對應地址上寫1,不顯示寫0,如下圖所示。所以SEG4地址應寫入的數據為0110 ,SEG5地址應寫入數據1101。
三、命令格式
HT1621 可以用軟件設置 兩種模式的命令可以配置 HT1621 和傳送 LCD 所顯示的數據。HT1621 的配置模式稱為命令模式,命令模式類型碼為 100。命令模式包括一個系統配置命令,一個系統頻率選擇命令,一個 LCD 配置命令,一個聲音頻率選擇命令,一個定時器/WDT設置命令和一個操作命令。數據模式包括 READ,WRITE 和 READ-MODIFY-WRITE 操作,下表是數據和命令模式類型碼表。
| 操作 | 模式 | 類型碼 |
|---|---|---|
| READ | 數據 | 110 |
| WRITE | 數據 | 101 |
| READ-MODIFY-RITE | 數據 | 101 |
| COMMAND | 命令 | 100 |
模式命令應在數據或命令傳送前運行。如果執行連續的命令,命令模式代碼即 100,將被忽略。當系統在不連續命令模式或不連續地址數據模式下,管腳/CS 應設為 “1” 而且先前的操作模式將復位。當管腳/CS 返回 “0” 時,新的操作模式類型碼應先運行。
四、時序圖及程序流程
五、硬件連接
| 功能口 | 引腳 |
|---|---|
| CS | PB.12 |
| DATA | PB.14 |
| WR | PB.13 |
六、移植文件
注意:延時函數使用了FreeRTOS的vTaskDelay任務延時函數
鏈接:https://pan.baidu.com/s/1lXWqJIr9Q07al4H3FwNb6Q 提取碼:dsuy
將 board_ht1621.c、board_ht1621.h 兩個文件加入到工程
6.1 board_ht1621.c
/********************************************************************** INCLUDES*/
#include "FreeRTOS.h"
#include "task.h"#include "board_ht1621.h"static void gpioConfig(void);/********************************************************************** PUBLIC FUNCTIONS*/
/**@brief 初始化LCD屏,HT1621芯片@param 無@return 無
*/
void HT1621_Init(void)
{gpioConfig();vTaskDelay(10);LCD_CS_1();LCD_DATA_1();LCD_WR_1();vTaskDelay(100); // 延時使LCD工作電壓穩定HT1621_WriteCommand(HT1621_SYS_EN); // 打開系統振蕩器HT1621_WriteCommand(HT1621_BIAS); // BIAS 13 4個公共口HT1621_WriteCommand(HT1621_RC256); // 使用RC_256K系統時鐘源,片內RC振蕩器HT1621_WriteCommand(HT1621_WDT_DIS);HT1621_WriteCommand(HT1621_LCD_ON);
}/**@brief 寫入命令,命令標志100@param cmd -[in] 命令數據@return 無
*/
void HT1621_WriteCommand(uint8_t cmd)
{uint8_t i;LCD_CS_0(); // CS = 0 vTaskDelay(1);// 寫入命令標志,DATA:100LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_1(); // DATA = 1vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_0(); // DATA = 0vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_0(); // DATA = 0vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);// Datasheet中命令后的C8為0LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_0(); // DATA = 0vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);// Datasheet中命令后的C7~C0for(i = 0; i < 8; i++){LCD_WR_0(); // WR = 0vTaskDelay(1);if((cmd << i) & 0x80){LCD_DATA_1(); // DATA = 1}else{LCD_DATA_0(); // DATA = 0}vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);}LCD_CS_1(); // CS = 1vTaskDelay(1);
}/**@brief 寫入4位數據,寫入數據標志101@param addr -[in] 寫入起始地址@param data -[in] 寫入數據,因為HT1621的數據位4位,所以實際寫入數據為參數的后4位@return 無
*/
void HT1621_WriteData4Bit(uint8_t addr, uint8_t data)
{uint8_t i;LCD_CS_0(); // CS = 0 vTaskDelay(1);// 寫入數據標志,DATA:101LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_1(); // DATA = 1vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_0(); // DATA = 0vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_1(); // DATA = 1vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);// 寫入地址,Datasheet中A5~A0for(i = 0; i < 6; i++){LCD_WR_0(); // WR = 0vTaskDelay(1);if((addr << i) & 0x80){LCD_DATA_1(); // DATA = 1}else{LCD_DATA_0(); // DATA = 0}vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);}// 寫入數據,Datasheet中D0~D3for(i = 0; i < 4; i++){LCD_WR_0(); // WR = 0vTaskDelay(1);if((data >> (3 - i)) & 0x01){LCD_DATA_1(); // DATA = 1}else{LCD_DATA_0(); // DATA = 0}vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);}LCD_CS_1(); // CS = 1vTaskDelay(1);
}/**@brief 寫入8位數據,寫入數據標志101@param addr -[in] 寫入起始地址@param data -[in] 寫入數據@return 無
*/
void HT1621_WriteData8Bit(uint8_t addr, uint8_t data)
{uint8_t i;LCD_CS_0(); // CS = 0 vTaskDelay(1);// 寫入數據標志,DATA:101LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_1(); // DATA = 1vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_0(); // DATA = 0vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);LCD_WR_0(); // WR = 0vTaskDelay(1);LCD_DATA_1(); // DATA = 1vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);// 寫入地址,Datasheet中A5~A0for(i = 0; i < 6; i++){LCD_WR_0(); // WR = 0vTaskDelay(1);if((addr << i) & 0x80){LCD_DATA_1(); // DATA = 1}else{LCD_DATA_0(); // DATA = 0}vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);}// 寫入數據,Datasheet中兩組D0~D3for(i = 0; i < 8; i++){LCD_WR_0(); // WR = 0vTaskDelay(1);if((data >> (7 - i)) & 0x01){LCD_DATA_1(); // DATA = 1}else{LCD_DATA_0(); // DATA = 0}vTaskDelay(1);LCD_WR_1(); // WR = 1vTaskDelay(1);}LCD_CS_1(); // CS = 1vTaskDelay(1);
}/********************************************************************** LOCAL FUNCTIONS*/
/**@brief 引腳初始化@param 無@return 無
*/
static void gpioConfig(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(HT1621_CS_CLK|HT1621_DATA_CLK|HT1621_WR_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = HT1621_CS_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(HT1621_CS_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = HT1621_DATA_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(HT1621_DATA_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = HT1621_WR_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(HT1621_WR_PORT, &GPIO_InitStructure);
}/****************************************************END OF FILE****************************************************/
6.2 board_ht1621.h
#ifndef _BOARD_HT1621_H_
#define _BOARD_HT1621_H_/********************************************************************** INCLUDES*/
#include "stm32f10x.h"/********************************************************************** DEFINITIONS*/
#define HT1621_CS_PORT GPIOB // GPIO端口
#define HT1621_CS_CLK RCC_APB2Periph_GPIOB // GPIO端口時鐘
#define HT1621_CS_PIN GPIO_Pin_12 // 定義HT1621的CS管腳#define HT1621_DATA_PORT GPIOB // GPIO端口
#define HT1621_DATA_CLK RCC_APB2Periph_GPIOB // GPIO端口時鐘
#define HT1621_DATA_PIN GPIO_Pin_14 // 定義HT1621的DATA管腳#define HT1621_WR_PORT GPIOB // GPIO端口
#define HT1621_WR_CLK RCC_APB2Periph_GPIOB // GPIO端口時鐘
#define HT1621_WR_PIN GPIO_Pin_13 // 定義HT1621的WR管腳#define LCD_CS_0() GPIO_ResetBits(HT1621_CS_PORT, HT1621_CS_PIN)
#define LCD_CS_1() GPIO_SetBits(HT1621_CS_PORT, HT1621_CS_PIN)
#define LCD_DATA_0() GPIO_ResetBits(HT1621_DATA_PORT, HT1621_DATA_PIN)
#define LCD_DATA_1() GPIO_SetBits(HT1621_DATA_PORT, HT1621_DATA_PIN)
#define LCD_WR_0() GPIO_ResetBits(HT1621_WR_PORT, HT1621_WR_PIN)
#define LCD_WR_1() GPIO_SetBits(HT1621_WR_PORT, HT1621_WR_PIN)#define COMMAND_CODE 0x80 // 命令碼
#define WRITE_DATA_CODE 0xA0 // 寫命令#define HT1621_BIAS 0x52 // 1/3duty 4com
#define HT1621_SYS_DIS 0x00 // 關振系統蕩器和LCD偏壓發生器
#define HT1621_SYS_EN 0x02 // 打開系統振蕩器
#define HT1621_LCD_OFF 0x04 // 關閉LCD偏壓
#define HT1621_LCD_ON 0x06 // 打開LCE偏壓
#define HT1621_XTAL 0x28 // 外部接時鐘
#define HT1621_RC256 0x30 // 內部時鐘
#define HT1621_WDT_DIS 0X0A // 關閉看門狗
#define HT1621_TONE_ON 0x12 // 打開聲音輸出
#define HT1621_TONE_OFF 0x10 // 關閉聲音輸出/********************************************************************** API FUNCTIONS*/
void HT1621_Init(void);
void HT1621_WriteCommand(uint8_t cmd);
void HT1621_WriteData4Bit(uint8_t addr, uint8_t data);
void HT1621_WriteData8Bit(uint8_t addr, uint8_t data);#endif /* _BOARD_HT1621_H_ */
七、使用例子
/********************************************************************** DEFINITIONS*/
#define TEMP_ADDR 0x00
#define FOURTH_8_MHz_ADDR 0x04
#define FOURTH_8_ADDR 0x08
#define THIRD_8_75us_ADDR 0x0C
#define THIRD_8_ADDR 0x10
#define SECOND_8_POINT_ADDR 0x14
#define SECOND_8_ADDR 0x18
#define FIRST_8_50us_ADDR 0x1C
#define FIRST_8_ADDR 0x20
#define FM_SOUND_1_ADDR 0x24
#define SIGNAL_ADDR 0x28#define DISPLAY_ALARM 0x03
#define DISPLAY_FM 0x04
#define DISPLAY_1_1 0x08
#define DISPLAY_MHZ 0x10HT1621_Init();
HT1621_WriteData4Bit(TEMP_ADDR, 0x00); // ℃滅
HT1621_WriteData4Bit(SIGNAL_ADDR, 0x00); // 信號滅
HT1621_WriteData4Bit(FM_SOUND_1_ADDR, DISPLAY_ALARM | DISPLAY_FM); // 報警+FM亮
HT1621_WriteData8Bit(FOURTH_8_MHz_ADDR, DISPLAY_MHZ); // MHz亮/**@brief LCD屏顯示頻率@param frequency -[in] 頻率@return 無
*/
void LCD_ShowFrequency(uint32 frequency)
{calculateHundreds(frequency); // 百位calculateTens(frequency); // 十位calculateOnes(frequency); // 個位calculateDecimals(frequency); // 小數位
}/**@brief 計算頻率百位,如87.5MHz,則百位0@param frequency -[in] 頻率@return 無
*/
static void calculateHundreds(uint32 frequency)
{if(frequency / 100000 == 1){s_alarm |= DISPLAY_1_1;HT1621_WriteData4Bit(FM_SOUND_1_ADDR, s_alarm); // 1亮}else{s_alarm &= 0x07;HT1621_WriteData4Bit(FM_SOUND_1_ADDR, s_alarm); // 1滅}
}/**@brief 計算頻率十位,如87.5MHz,則十位8@param frequency -[in] 頻率@return 無
*/
static void calculateTens(uint32 frequency)
{if(frequency / 10000 % 10 == 0){HT1621_WriteData8Bit(FIRST_8_50us_ADDR, 0xAF); // 0}else if(frequency / 10000 % 10 == 8){HT1621_WriteData8Bit(FIRST_8_50us_ADDR, 0xEF); // 8}else if(frequency / 10000 % 10 == 9){HT1621_WriteData8Bit(FIRST_8_50us_ADDR, 0xED); // 9}
}/**@brief 計算頻率個位,如87.5MHz,則個位7@param frequency -[in] 頻率@return 無
*/
static void calculateOnes(uint32 frequency)
{if(frequency / 1000 % 10 == 0){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xBF); // 0.}else if(frequency / 1000 % 10 == 1){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xB0); // 1.}else if(frequency / 1000 % 10 == 2){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xDB); // 2.} else if(frequency / 1000 % 10 == 3){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xF9); // 3.} else if(frequency / 1000 % 10 == 4){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xF4); // 4.}else if(frequency / 1000 % 10 == 5){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0x7D); // 5.}else if(frequency / 1000 % 10 == 6){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0x7F); // 6.}else if(frequency / 1000 % 10 == 7){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xB8); // 7.}else if(frequency / 1000 % 10 == 8){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xFF); // 8.}else if(frequency / 1000 % 10 == 9){HT1621_WriteData8Bit(SECOND_8_POINT_ADDR, 0xFD); // 9.}
}/**@brief 計算頻率小數位,如87.5MHz,則小數位5@param frequency -[in] 頻率@return 無
*/
static void calculateDecimals(uint32 frequency)
{if(frequency / 100 % 10 == 0){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xAF); // 0}else if(frequency / 100 % 10 == 1){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xA0); // 1}else if(frequency / 100 % 10 == 2){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xCB); // 2} else if(frequency / 100 % 10 == 3){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xE9); // 3} else if(frequency / 100 % 10 == 4){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xE4); // 4}else if(frequency / 100 % 10 == 5){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0x6D); // 5}else if(frequency / 100 % 10 == 6){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0x6F); // 6}else if(frequency / 100 % 10 == 7){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xA8); // 7}else if(frequency / 100 % 10 == 8){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xEF); // 8}else if(frequency / 100 % 10 == 9){HT1621_WriteData8Bit(THIRD_8_75us_ADDR, 0xED); // 9}
}
? 由 Leung 寫于 2020 年 7 月 14 日
? 參考:STM32液晶顯示HT1621驅動原理及程序代碼
HT1621B段碼 LCD屏驅動 51單片機驅動程序
HT1621測試程序
總結
以上是生活随笔為你收集整理的STM32F103学习笔记(4)——LCD段码屏HT1621使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 牛客题霸 [进制转换] C++题解/答案
- 下一篇: Acronis Disk Directo