#技术资源# #申请原创#
一、 硬件连接电路
根据TM1621B的手册来看,硬件搭接电路很简单,只需要将CS,RD,WR,DATA分别连接MCU的引脚就行,MCU使用的是GD32F103RCT6,这里将电路图给出
(但是我在这里有个疑问,官方的手册上写的是VLCD必须比VDD,但是在实际测的时候,两个引脚的电压差不多,并没有很大的差别,不知道有没有懂得大神解释一下。)
二、液晶显示的数据原理
这里我先贴上我的液晶显示的厂家文件
在这里说明一下如何进行选择点亮自己想要的数据,可以看见这里有COM4,COM3,COM2,COM1这个其实是数据位,那么地址位其实就是seg,seg是按照十进制进行传输的
就比如,(--,X3,X2,X1)这一列,首先你要先选种这个地址,再进行传输,而(--,X3,X2,X1)对应的是 1 引脚的意思,那么要进行显示的时候,就可以用这样的表示-> (0x01,0x7),相当于制冷,负号,制热都给你点亮,其他的以此类推是一样的。
这里还可以举一个例子,比如第一个数字要表示0,他的数据位是(1D,1E,1G,1F)和(--,1C,1B,1A)那他们对应的地址即引脚是什么?对,是3脚和4脚所以可以表示为(0X03,0X0D),(0X04,0X07)。
这里提一嘴,地址是从高位写入,数据位是从低位写入。
这样就可以完成一个灯的点亮。
三、代码
LCD.c
#include "gd32f10x.h"
#include "LCD.h"
#include "delay.h"
void LCD_GPIO_Config(void)
{
rcu_periph_clock_enable(RCU_GPIOB);//初始化GPIOB时钟
rcu_periph_clock_enable(RCU_GPIOD);//初始化GPIOD时钟
rcu_periph_clock_enable(RCU_GPIOC);//初始化GPIOD时钟
rcu_periph_clock_enable(RCU_GPIOA);//初始化GPIOD时钟
gpio_init(GPIOD, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);//CS控制引脚
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);//RD控制引脚
gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);//WR控制引脚
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5);//DATA控制引脚
//先默认高电平
gpio_bit_set(GPIOD,GPIO_PIN_2);
gpio_bit_set(GPIOA,GPIO_PIN_8);
gpio_bit_set(GPIOC,GPIO_PIN_9);
gpio_bit_set(GPIOB,GPIO_PIN_5);
}
/********************从高位写入数据*************************/
void Write_Data_H(uint8_t Data, uint8_t Cnt) //Data的高cnt位写入TM1621,高位在前
{
uint8_t i;
for(i=0; i<Cnt; i++)
{
WR_OUT(0);//输出低电平
if(Data&0x80) //从最高位发送
{
DATA_OUT(1);
}
else
{
DATA_OUT(0);
}
delay_1us(2);
WR_OUT(1);
Data<<=1;
delay_1us(2);
}
WR_OUT(0);
DATA_OUT(0);
}
/********************从低位写入数据*************************/
void Write_Data_L(uint8_t Data,uint8_t Cnt) //Data 的低cnt位写入TM1621,低位在前
{
uint8_t i;
for(i=0;i<Cnt;i++)
{
WR_OUT(0);
if(Data&0x01) //从低位发送
{
DATA_OUT(1);
}
else
{
DATA_OUT(0);
}
delay_1us(2);
WR_OUT(1);
Data>>=1;
delay_1us(2);
}
WR_OUT(0);
DATA_OUT(0);
}
/********************写入控制命令*************************/
void WriteCmd(uint8_t Cmd)
{
CS_OUT(0);
delay_1us(2);
Write_Data_H(0x80,4); //写入命令标志100
Write_Data_H(Cmd,8); //写入命令数据
CS_OUT(1);
delay_1us(2);
}
/*********指定地址写入数据,实际写入8位************/
void WriteOneData_8(uint8_t Addr, uint8_t Data)
{
CS_OUT(0);
Write_Data_H(0xa0,3); //写入数据标志101
Write_Data_H(Addr<<2,6); //写入地址数据
Write_Data_L(Data,8); //写入数据
CS_OUT(1);
delay_1us(2);
}
/*********指定地址写入数据,实际写入后4位************/
void WriteOneData_4(uint8_t Addr, uint8_t Data)
{
CS_OUT(0);
Write_Data_H(0xa0,3); //写入数据标志101
Write_Data_H(Addr<<2,6); //写入地址数据
Write_Data_L(Data,4); //写入数据
CS_OUT(1);
delay_1us(2);
}
/*********连续写入方式,每次数据为8位,写入数据************/
void WriteAllData(uint8_t Addr,uint8_t *p,uint8_t cnt)
{
uint8_t i;
CS_OUT(0);
Write_Data_H(0xa0,3); //写入数据标志101
Write_Data_H(Addr<<2,6); //写入地址数据
for(i=0;i<cnt;i++) //写入数据
{
Write_Data_L(*p,8);
p++;
}
CS_OUT(1);
delay_1us(2);
}
/*******************TM1621初始化**********************/
void TM1621_init(void)
{
CS_OUT(1);
WR_OUT(1);
DATA_OUT(1);
delay_1us(5);
delay_1ms(1);
WriteCmd(BIAS1_3); //1/3偏压 4公共口
WriteCmd(RC_256K); //内部RC振荡
WriteCmd(SYS_DIS); //关系统振荡器和LCD偏压发生器
WriteCmd(WDT_DIS); //禁止看门狗
WriteCmd(SYS_EN); //打开系统振荡器
WriteCmd(LCD_ON); //开LCD偏压
}
LCD.H
#include "gd32f10x.h"
/*
当/CS为高电平读写TM1621B的数据和命令无效,串行接口电路复位;
当/CS为低电平和作为输入时,读写TM1621B的数据和命令有效
*/
#define CS_OUT(a) if(a) gpio_bit_set(GPIOD,GPIO_PIN_2); else gpio_bit_reset(GPIOD,GPIO_PIN_2);
/*
在/RD信号的下降沿,TM1621B内存的数据被读到DATA 线上,
主控制器可以在下一个上升沿时锁存这些数据
*/
#define RD_OUT(a) if(a) gpio_bit_set(GPIOA,GPIO_PIN_8); else gpio_bit_reset(GPIOA,GPIO_PIN_8);
/*
在/WR信号的上升沿,DATA 线上的数据写到TM1621B
*/
#define WR_OUT(a) if(a) gpio_bit_set(GPIOC,GPIO_PIN_9); else gpio_bit_reset(GPIOC,GPIO_PIN_9);
/*
外接上拉电阻的串行数据逻辑输入/输出
*/
#define DATA_OUT(a) if(a) gpio_bit_set(GPIOB,GPIO_PIN_5); else gpio_bit_reset(GPIOB,GPIO_PIN_5);
#define SYS_DIS 0X00 //关闭系统振荡器和LCD 偏压发生器
#define SYS_EN 0X02 //打开系统振荡器
#define LCD_OFF 0X04 //关闭LCD 偏压发生器
#define LCD_ON 0X06 //打开LCD 偏压发生器
#define TIMER_DIS 0X08 //时基输出失效
#define WDT_DIS 0X0A //WDT溢出标志输出失效
#define TIMER_EN 0X0C //时基输出使能
#define WDT_EN 0X0E //WDT 溢出标志输出有效
#define TONE_OFF 0X10 //关闭声音输出
#define TONE_ON 0X12 //打开声音输出
#define CLR_TIMER 0X18 //时基发生器清零
#define CLR_WDT 0X1C //清除WDT 状态
#define XTAL_32K 0X28 //系统时钟源晶振
#define RC_256K 0X30 //系统时钟源片内RC振荡器
#define EXT_256K 0X38 //系统时钟源外部时钟源
#define BIAS1_2 0X50 //1/2的偏压四个公共口
#define BIAS1_3 0X52 //1/3的偏压4个公共口
#define TONE_4K 0X80 //声音频率4KHz
#define TONE_2K 0XC0 //声音频率2KHz
#define IRQ_DIS 0X20 //使/IRQ 输出失效
#define IRQ_EN 0X30 //使/IRQ 输出有效
#define F1 0X40 //时基时钟输出1Hz,WDT计时标志产生时间:4S
#define F2 0X42 //时基时钟输出2Hz,WDT计时标志产生时间:2S
#define F4 0X44 //时基时钟输出4Hz,WDT计时标志产生时间:1S
#define F8 0X46 //时基时钟输出8Hz,WDT计时标志产生时间:1/2S
#define F16 0X48 //时基时钟输出16Hz,WDT计时标志产生时间:1/4S
#define F32 0X4A //时基时钟输出32Hz,WDT计时标志产生时间:1/8S
#define F64 0X4C //时基时钟输出64Hz,WDT计时标志产生时间:1/16S
#define F128 0X4E //时基时钟输出128Hz,WDT计时标志产生时间:1/32S
#define TOPT 0XC0 //测试模式
#define TNORMAL 0XC6 //普通模式
void LCD_GPIO_Config(void);
void Write_Data_H(uint8_t Data, uint8_t Cnt);
void Write_Data_L(uint8_t Data,uint8_t Cnt);
void WriteCmd(uint8_t Cmd);
void WriteOneData_8(uint8_t Addr, uint8_t Data);
void WriteAllData(uint8_t Addr,uint8_t *p,uint8_t cnt);
void TM1621_init(void);
void WriteOneData_4(uint8_t Addr, uint8_t Data);
void WriteOneData_8(uint8_t Addr, uint8_t Data)
void WriteOneData_4(uint8_t Addr, uint8_t Data)
这里主要说一下这两个函数,
第一个函数void WriteOneData_8(uint8_t Addr, uint8_t Data)
在你写入地址的时候,他会将后一位地址也写入,数据也会多读4位
如WriteOneData_8(0x03,0x77);就相当于他一次性写入了(0x03,0x07)和(0x04,0x07);的意思
第二个函数void WriteOneData_4(uint8_t Addr, uint8_t Data)
在你写入一个地址就对一个数据,如WriteOneData_4(0x03,0x77);
就会变成(0x03,0x07);不会顺延地址,也不会写入高4位。
这个在不同厂家的显示屏的时候就可以很灵活的使用。
四、实物展示
新手一名,如果有理解错误的地方大家多多包含并指出,感谢
|
|
感谢大佬分享,21家的原创奖励需文章字数至少800,您可以继续填充内容哦~