LCD控制器TM1621/HT1621
要点
1)由公共输出口COM0-COM3和段输出口SEG0-SEG23控制LCD的段码;
2)3个关键数据口:
a)CS:片选,低电平有效;
b)WR:读写控制,上升沿从MCU读取数据;
c)DATA:数据,命令是大端位序,数据是小端位序;
3)命令结构:3bit标识(LCD_FLAG_CMD)+9bit命令
4)写数据到RAM:3bit标识(LCD_FLAG_DATA)+6bit地址+若干bit数据(数据是小端)
定义
#define LCD_BIAS_1P2 (0<<1) //1/2偏压
#define LCD_BIAS_1P3 (1<<1) //1/3偏压
#define LCD_USE_COM2 (0<<3) //使用2个公共口
#define LCD_USE_COM3 (1<<3) //使用3个公共口
#define LCD_USE_COM4 (2<<3) //使用4个公共口
#define LCD_CMD_BIAS_COM (0x40) //设置公共口和偏压的命令
#define LCD_CMD_ON (0x6) //打开
#define LCD_CMD_OFF (0x4) //关闭
#define LCD_CMD_Normal (0x1C6) //普通模式
#define LCD_CMD_SYS_EN (2) //打开系统振荡器和LCD偏压发生器
#define LCD_CMD_SYS_DIS (0) //关闭系统振荡器和LCD偏压发生器
#define LCD_RC256 (0x30) //系统时钟源片内RC 256K振荡器
#define LCD_XTAL 0x28 //0b1000 0010 1000 外部接时钟
#define LCD_WDTDIS1 0X0A //0b1000 0000 1010 禁止看门狗
#define LCD_FLAG_CMD (4) //命令标识100
#define LCD_FLAG_DATA (5) //数据标识101
一些函数
/**
* 发送大端数据
*/
static void lcd_sendBeData(LcdStr* ps,u32 n, int nBit) {
for (int i = nBit; --i >= 0;) {
LCD_WR_L();
LCD_WriteBit((n >> i) & 1);
LCD_DELAY();
LCD_WR_H();
LCD_DELAY();
}
}
/**
* 发送小端数据
*/
static void lcd_sendLeData(LcdStr* ps,u32 n, int nBit) {
for (int i = 0; i < nBit; i++) {
LCD_WR_L();
LCD_WriteBit((n >> i) & 1);
LCD_DELAY();
LCD_WR_H();
LCD_DELAY();
}
}
/**
*写命令
*/
static void lcd_writeCmd(LcdStr* ps, u16 cmd) {
LCD_CS_SEL();
lcd_sendBeData(ps, LCD_FLAG_CMD, 3); //100
lcd_sendBeData(ps, cmd, 9);
LCD_CS_RELAESE();
LCD_DELAY();
}
初始化
static void lcd_init(LcdStr* ps) {
...//MCU的GPIO初始化
LCD_CS_RELAESE();//片选脚拉高
LCD_WR_H(); //读写控制拉高
LCD_DELAY();
//---------------
lcd_writeCmd(ps, LCD_CMD_BIAS_COM | LCD_USE_COM4 | LCD_BIAS_1P3);//1/3偏压 4公共口
lcd_writeCmd(ps, LCD_RC256); //内部RC振荡
lcd_writeCmd(ps, LCD_CMD_SYS_DIS); //关系统振荡器和LCD偏压发生器
lcd_writeCmd(ps, LCD_WDTDIS1);
lcd_writeCmd(ps, LCD_CMD_SYS_EN); //打开系统振荡器
lcd_writeCmd(ps, LCD_CMD_Normal);
lcd_writeCmd(ps, LCD_CMD_ON); //开LCD偏压
lcd_clearAll(ps); //清除屏幕数据,就是全部写0
}
显示
/**
* 显示所有
*/
static void lcd_showAll(LcdStr* ps) {
LCD_CS_SEL();
lcd_sendBeData(ps, LCD_FLAG_DATA, 3); //标识101
lcd_sendBeData(ps, ps->startSeg, 6); //地址
for (int s = 0; s < 4; s++) {
lcd_sendLeData(ps, ps->lcds >> (s * 8), 8);
}
LCD_CS_RELAESE();
LCD_DELAY();
}
清除
/**
*清除屏幕
*/
static void lcd_clearAll(LcdStr* ps) {
LCD_CS_SEL();
lcd_sendBeData(ps, LCD_FLAG_DATA, 3);
lcd_sendBeData(ps, 0, 6); //地址
for (int s = 0; s < 16; s++) {
lcd_sendLeData(ps, 0, 8);
}
LCD_CS_RELAESE();
LCD_DELAY();
}