变更历史
1、2021年12月27日,初版
2、2022年1月15日,增加一些心得
3、2022年2月25日,驱动程序在HT1632D上测试通过
4、2022年5月24日,增加连续写函数(命令模式和数据模式各一),在HT1632C上测试通过
5、2022年7月6日,数据模式写函数修正,在HT1632D上测试通过
6、2023年1月15日,调整DATA线操作时机的建议
7、2024年1曰10日,HAL层初始化补全
概述
芯片概述
HT1632C是一款常用的LED点阵屏驱动芯片,支持NMOS或PMOS的共阳/阴布线,支持32ROWx8COM或24ROWx16COM点阵布局。芯片手册的翻译请参考文章:《合泰HT1632C芯片手册 精炼汉化版》
HT1632C仅支持串行通信,有4条通信线,分别是:
- CS:低电平有效
- WR:写时钟,上升沿有效
- RD: 读时钟,下降沿有效
- DATA:数据线
其指令集有两种,一种是12bit的CMD(配置)模式,另一种是14bit的DATA(VRAM数据)模式。
- Cmd模式:3bit命令码 - 8bit配置 - 1bit任意值
设计理念
我将使用GPIO模拟方式进行设计。我手中的HT1632C开发板是32ROWx8COM + NMOS布局的。测试平台为ST的STM32F1和Renesas的RX130。
原因:
- 一般的,MCU硬件SPI的数据线与HT1632C的IO不能完整对应,硬件SPI往往是:CLK、MOSI、MISO,即1条时钟线+2条数据线,只能够实现50%的功能(读or写)。
- 另一个问题是:一般的单片机的硬件SPI不支持变长数据的发送。
- 使用GPIO模拟方式,可以实现100%的功能(读+写),还能获得可跨平台的可移植性。
为了省事,我只写出两种模式下的写入函数。
HT1632C的驱动
这款芯片的驱动将采用分层设计。
- 硬件抽象层HAL,包含:GPIO初始化函数,GPIO输出函数。
- 硬件驱动层HDL,包含:CMD模式-写入函数,DATA模式-写入函数,HT1632C指令集的常数定义。
- 功能模块层FML,包含:HT1632C初始化函数,LED全亮函数,LED全灭函数。
硬件抽象层HAL
ht1632c_hal.c,主体为GPIO初始化函数。如下。
1、初始化四条GPIO,均为推挽输出。优先初始化CS:先将其输出寄存器bit置位,再初始化为输出,以防HT1632C被选中。
如果使用“读数据”功能,需要将DATA线初始化为开漏输出,并配备外部上拉。
2、四条GPIO的输出函数,形如HT1632xHAL_***WriteBit(uint8_t bit_status)。
硬件驱动层HDL
ht1632c_hdl.c,主体为CMD模式-写入函数,VRAM模式-写入函数。如下。
为了保证WR上升沿时DATA线电压的稳定,建议在两次WR上升沿的时间中点操作DATA线。
/*
FUNCTION : HT1632xHDL_CmdModeWrite
DESCRIPTION : Fast write function of Cmd-Mode.
INPUT : u11_cmd: head address of Cmd array. This parameter will be
left-shifted 1-bit within the function to add 1 useless bit.
3bits(cmd) - 7bits(vram addr) - 4bits(vram data)
OUTPUT : None
DATE :
*/
void HT1632xHDL_CmdModeWrite(uint16_t u11_cmd[], uint16_t length) {
uint16_t i, j;
uint16_t u12_cmd;
/* Write Process */
HT1632xHAL_CSWriteBit(Bit_RESET); /* Chip selected */
for (j = 0; j < length; j++) { /* From u11_cmd[0] to u11_cmd[length-1] */
/* Cmd Prepare */
u12_cmd = u11_cmd[j] << 1U; /* expand to 12bits */
/* Write the cmd */
if (j == 0) { /* Send u11_cmd[zero] */
for (i = 1<<11U; i != 0; i >>= 1) { /* MSB: From bit11 to bit0 */
HT1632xHAL_WRWriteBit(Bit_RESET); /* Reset WR_CLK */
HT1632xHAL_DATAWriteBit( ( !!(u12_cmd & i) )? Bit_SET:Bit_RESET ); /* DATA_OUT(H/L) = DATA_Bit(1/0) */
HT1632xHAL_WRWriteBit(Bit_SET); /* Set WR_CLK */
}
} else { /* Send u11_cmd[non-zero] */
for (i = 1<<8U; i != 0; i >>= 1) { /* MSB: From bit8 to bit0 */
HT1632xHAL_WRWriteBit(Bit_RESET); /* Reset WR_CLK */
HT1632xHAL_DATAWriteBit( ( !!(u12_cmd & i) )? Bit_SET:Bit_RESET ); /* DATA_OUT(H/L) = DATA_Bit(1/0) */
HT1632xHAL_WRWriteBit(Bit_SET); /* Set WR_CLK */
}
}
}
HT1632xHAL_CSWriteBit(Bit_SET); /* Chip un-selected */
}
/*
FUNCTION : HT1632xHDL_DataModeWrite
DESCRIPTION : Fast write function of Data array.
INPUT : u14_data: head address of HT1632C DATA Array
3bits(cmd) - 7bits(vram addr) - 4bits(pixel on/off info)
OUTPUT : None
DATE :
*/
void HT1632xHDL_DataModeWrite(uint16_t u14_data[], uint16_t length) {
uint16_t i, j;
/* Write Process */
HT1632xHAL_CSWriteBit(Bit_RESET); /* Chip selected */
for (j = 0; j < length; j++) { /* From u11_cmd[0] to u14_data[length-1] */
/* Write the cmd */
if (j == 0) { /* Send u14_data[zero] */
for (i = 1<<13U; i != 0; i >= 1) { /* MSB: From bit13 to bit0 */
HT1632xHAL_WRWriteBit(Bit_RESET); /* Reset WR_CLK */
HT1632xHAL_DATAWriteBit( ( !!(u14_data[j] & i) )? Bit_SET:Bit_RESET ); /* DATA_OUT(H/L) = DATA_Bit(1/0) */
HT1632xHAL_WRWriteBit(Bit_SET); /* Set WR_CLK */
}
} else { /* Send u14_data[non-zero] */
for (i = 1<<3U; i != 0; i >= 1) { /* MSB: From bit3 to bit0 */
HT1632xHAL_WRWriteBit(Bit_RESET); /* Reset WR_CLK */
HT1632xHAL_DATAWriteBit( ( !!(u14_data[j] & i) )? Bit_SET:Bit_RESET ); /* DATA_OUT(H/L) = DATA_Bit(1/0) */
HT1632xHAL_WRWriteBit(Bit_SET); /* Set WR_CLK */
}
}
}
HT1632xHAL_CSWriteBit(Bit_SET); /* Chip un-selected */
}
/**********************************************************END OF FILE****/
ht1632c_hdl.h,主体为HT1632C的指令集。如下。
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __HT1632X_HDL_H
#define __HT1632X_HDL_H
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Typedef -------------------------------------------------------------------*/
/* Marco ---------------------------------------------------------------------*/
/*
HT1632C/D Instruction set Definition
*/
/* CMD type */
#define CM_CFG 0x400 /* HT1632C command mode(DM): configure read/write */
#define DM_READ 0x3000 /* HT1632C data mode(CM): VRAM read */
#define DM_WRITE 0x2800 /* HT1632C data mode(CM): VRAM write */
#define DM_READ_WRITE 0x2800 /* HT1632C data mode(CM): VRAM read modify write*/
/* CM: system on/off */
#define CM_SYSDIS 0x00 /* System disable */ /* Default */
#define CM_SYSEN 0x01 /* System enable */
/* CM: led on/off */
#define CM_LEDOFF 0x02 /* led pwm generator DIS */ /* Default */
#define CM_LEDON 0x03 /* led pwm generator EN */
/* CM: blink on/off */
#define CM_BLINKOFF 0x0408 /* Blink OFF */ /* Default */
#define CM_BLINKON 0x0409 /* Blink ON */
/* CM: slave/master */
#define CM_SLAVE 0x10 /* Slave mode */
#define CM_RC_MASTER 0x18 /* RC master mode */ /* Default */
#define CM_EXTCK_MASTER 0x1C /* EXT clock master mode */
/* CM: Circuit layout: N/P-MOS & COM config */
#define CM_LAYOUT_N_8COM 0x20 /* NMOS & 8-COM */
#define CM_LAYOUT_N_16COM 0x24 /* NMOS & 16-COM */
#define CM_LAYOUT_P_8COM 0x28 /* PMOS & 8-COM */
#define CM_LAYOUT_P_16COM 0x2C /* PMOS & 16-COM */
/* CM: PWM Ratio configuration (Brightness) */
#define CM_PWM_(r) (uint16_t)(0x04A0|((r <= 16 && r >= 1)? ( r - 1 ):(0x000F))) /* PWM Ratio, r∈[1, 16], 16 is Default */
/* DM: VRAM Address */
#define DM_ADDR(n) (uint16_t)(n << 4) /* 8COM --> n∈[0, 63], 16COM --> n∈[0, 127] */
#define DM_ADDR_MASK 0x07F0 /* Addr bits mask, bit4~10 */
#define DM_ADDR_8COM_MAX 64 /* 8COM's MAX */ /* Do not init with (uint16_t) */
#define DM_ADDR_16COM_MAX 96 /* 16COM's MAX */ /* Do not init with (uint16_t) */
/* DM: Pixel location */
#define DM_LOCATION(n) ((uint32_t)(1 << ( 3 - n ))) /* n=0,1,2,3 */
#define DM_LOCATION_MASK 0x000F /* Loaction bits mask, bit0~3 */
/* Pixel Definition */
#define PIXEL(id) ((uint32_t)(DM_ADDR( (id / 4) ) | DM_LOCATION( (id % 4) )))
/* Constant ------------------------------------------------------------------*/
/* Variables -----------------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/
void HT1632xHDL_CmdModeWrite(uint16_t u11_cmd[], uint16_t length);
void HT1632xHDL_DataModeWrite(uint16_t u14_data[], uint16_t length);
#endif /* __HT1632X_HDL_H */
/****************************************************************** OF FILE****/
功能模块层FML
ht1632c_fml.c,主体为HT1632C初始化函数,LED全亮函数,LED全灭函数。
/**************************************************************************
FUNCTION : disp_fml_init
DESCRIPTION : Initializes display monitor.
INPUT : None
OUTPUT : None
UPDATE :
DATE :
**************************************************************************/
void disp_fml_init(void)
{
uint16_t i;
/* HT1632C init data */
uint16_t Init_Data[] = {
CM_CFG | CM_SYSDIS,
CM_CFG | CM_LAYOUT_N_8COM,
CM_CFG | CM_RC_MASTER,
CM_CFG | CM_PWM_(16),
CM_CFG | CM_BLINKOFF,
CM_CFG | CM_SYSEN,
CM_CFG | CM_LEDON,
};
/* Send init data */
HT1632xHDL_CmdModeWrite(Init_Data, sizeof(Init_Data)/sizeof(uint16_t));
}
/**************************************************************************
FUNCTION : disp_fml_disp_all_on
DESCRIPTION : Send vram data to ht1632c.
INPUT : None
OUTPUT : None
UPDATE :
DATE :
**************************************************************************/
void disp_fml_disp_all_on(void)
{
uint16_t i;
uint16_t u14_vram_data[DM_ADDR_8COM_MAX]= {0,};
/* Send VRAM data */
for (i = 0U; i< DM_ADDR_8COM_MAX; i++ )
{
u14_vram_data[i] = DM_WRITE | (i << 4) | DM_LOCATION_MASK;
}
HT1632xHDL_DataModeWrite(u14_vram_data, DM_ADDR_8COM_MAX);
}
/**************************************************************************
FUNCTION : disp_fml_disp_all_off
DESCRIPTION : Send vram data to ht1632c.
INPUT : None
OUTPUT : None
UPDATE :
DATE :
**************************************************************************/
void disp_fml_disp_all_off(void)
{
uint16_t i;
uint16_t u14_vram_data[DM_ADDR_8COM_MAX]= {0,};
/* Send VRAM data */
for (i = 0U; i< DM_ADDR_8COM_MAX; i++ )
{
u14_vram_data[i] = DM_WRITE | (i << 4);
}
HT1632xHDL_DataModeWrite(u14_vram_data, DM_ADDR_8COM_MAX);
}
展望
现在,你有鱼竿和鱼饵了。快去钓鱼吧!
比如,写个字库,实现数字的显示!