段码LCD驱动代码,简洁版。0.5s增加数字加1
本帖最后由 whoyzf 于 2024-11-5 18:10 编辑/*********************************************************/
#define MAIN_Fosc 11059200L //定义主时钟
#include "STC8H4K64TL.h"
/************* 功能说明 **************
888e
硬件连接及LCD_buff
SEG22 SEG21 SEG20 SEG19 SEG18 SEG17
12 3 4 10 9 8 7 6 5
COM0 3A 4A 2A 4D 1A 4G C0SEGV2
COM1 3B 3F 2B 2F 1B 1F C1SEGV2
COM2 3C 3G 2C 2G 1C 1G C2SEGV2
COM3 3D 3E 2D 2E 1D 1E C1SEGV2
******************************************/
/************* 本地常量声明 **************/
/************* 本地IO定义 **************/
/************* 本地变量声明 **************/
bit B_500mS; // 0.5秒时隙标志
bit B_20ms; // 20ms时隙标志
u8 OpTime; // 此变量非0时, 不睡眠, 连续运行程序(本例串口唤醒后连续运行5秒, 以便正确接收串口数据)
u8 uc0_5sflag=0;
/************* 本地函数声明 **************/
u8 Timer0_Config(u32 reload); //reload值是主时钟周期数
void LCD_config(void);
void ReadKey(void); //50ms call
unsigned char segmentCodes = {
0x3F, // 0 - a-g: 00011111
0x06, // 1 - a-g: 00000110
0x5B, // 2 - a-g: 01011011
0x4F, // 3 - a-g: 01001111
0x66, // 4 - a-g: 01100110
0x6D, // 5 - a-g: 01101101
0x7d, // 6 - a-g: 01111101
0x07, // 7 - a-g: 00000111
0x7F, // 8 - a-g: 01111111
0x6f// 9 - a-g: 01101111
};
/****************** 对第1~5数字装载显示函数 ***************************/
u8 code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e};
void displayThreeDigits(unsigned int number) ;
void updateSegments(unsigned char hundreds,unsigned char tens,unsigned char units);
// 函数用于显示一个三位数
void displayThreeDigits(unsigned int number) {
unsigned char hundreds ; // 百位
unsigned char tens ; // 十位
unsigned char units ; // 个位
hundreds = number / 100; // 百位
tens = (number / 10) % 10; // 十位
units = number % 10; // 个位
// 初始化寄存器
C0SEGV2 = 0x00;
C1SEGV2 = 0x00;
C2SEGV2 = 0x00;
C3SEGV2 = 0x00;
updateSegments(hundreds,tens,units);
}
// 函数用于更新段寄存器
void updateSegments(unsigned char hundreds,unsigned char tens,unsigned char units) {
// 左起第一位,控制1A到1G位
if ((segmentCodes & 0x01) == 0) C0SEGV2 &= 0xfb; else C0SEGV2 |= 0x04; // 1A位是0,或者1
if ((segmentCodes & 0x02) == 0) C1SEGV2 &= 0xfb; else C1SEGV2 |= 0x04; // 1B位是0,或者1
if ((segmentCodes & 0x04) == 0) C2SEGV2 &= 0xfb; else C2SEGV2 |= 0x04; // 1C位是0,或者1
if ((segmentCodes & 0x08) == 0) C3SEGV2 &= 0xfb; else C3SEGV2 |= 0x04; // 1D位是0,或者1
if ((segmentCodes & 0x10) == 0) C3SEGV2 &= 0xfd; else C3SEGV2 |= 0x02; // 1E位是0,或者1
if ((segmentCodes & 0x20) == 0) C1SEGV2 &= 0xfd; else C1SEGV2 |= 0x02; // 1F位是0,或者1
if ((segmentCodes & 0x40) == 0) C2SEGV2 &= 0xfd; else C2SEGV2 |= 0x02; // 1G位是0,或者1
// 左起第二位,控制2A到2G位
if ((segmentCodes & 0x01) == 0) C0SEGV2 &= 0xef; else C0SEGV2 |= 0x10;
if ((segmentCodes & 0x02) == 0) C1SEGV2 &= 0xef; else C1SEGV2 |= 0x10;
if ((segmentCodes & 0x04) == 0) C2SEGV2 &= 0xef; else C2SEGV2 |= 0x10;
if ((segmentCodes & 0x08) == 0) C3SEGV2 &= 0xef; else C3SEGV2 |= 0x10;
if ((segmentCodes & 0x10) == 0) C3SEGV2 &= 0xf7; else C3SEGV2 |= 0x08;
if ((segmentCodes & 0x20) == 0) C1SEGV2 &= 0xf7; else C1SEGV2 |= 0x08;
if ((segmentCodes & 0x40) == 0) C2SEGV2 &= 0xf7; else C2SEGV2 |= 0x08;
// 左起第三位,控制3A到3G位
if ((segmentCodes & 0x01) == 0) C0SEGV2 &= 0xbf; else C0SEGV2 |= 0x40;
if ((segmentCodes & 0x02) == 0) C1SEGV2 &= 0xbf; else C1SEGV2 |= 0x40;
if ((segmentCodes & 0x04) == 0) C2SEGV2 &= 0xbf; else C2SEGV2 |= 0x40;
if ((segmentCodes & 0x08) == 0) C3SEGV2 &= 0xbf; else C3SEGV2 |= 0x40;
if ((segmentCodes & 0x10) == 0) C3SEGV2 &= 0xdf; else C3SEGV2 |= 0x20;
if ((segmentCodes & 0x20) == 0) C1SEGV2 &= 0xdf; else C1SEGV2 |= 0x20;
if ((segmentCodes & 0x40) == 0) C2SEGV2 &= 0xdf; else C2SEGV2 |= 0x20;
}
void main(void)
{
unsigned char ucshow=0,i=0;
P0M1 = 0; P0M0 = 0;
P1M1 = 0; P1M0 = 0;
P2M1 = 0; P2M0 = 0;
P3M1 = 0X80; P3M0 = 0;
P4M1 = 0; P4M0 = 0;
P5M1 = 0; P5M0 = 0;
P6M1 = 0; P6M0 = 0;
P7M1 = 0; P7M0 = 0;
Timer0_Config(MAIN_Fosc / 50); //reload值是主时钟周期数,(中断频率, 50次/秒)
EA = 1;
P37=0;
// OpTime= 0;
// DisMode = 0;
// RTC_config();
LCD_config();
while(1)
{
if(uc0_5sflag==1)
{
uc0_5sflag=0;
ucshow++;
// COMLENM=ucshow;
// COMLENL=(255-ucshow);
// C0SEGV2=ucshow;
// C1SEGV2=ucshow;
// C3SEGV2=ucshow;
C0SEGV2 = 0x00;
C1SEGV2 = 0x00;
C2SEGV2 = 0x00;
C3SEGV2 = 0x00;
// 设置C0SEGV2, C1SEGV2, C2SEGV2, C3SEGV2寄存器
// C0SEGV2 = segValues;
// C1SEGV2 = segValues;
// C2SEGV2 = segValues;
// C3SEGV2 = segValues;
//i=8;
/*
//左起第一位,
if ((segmentCodes & 0x01) == 0) C0SEGV2 &= 0xfb; // 1A位是0
else C0SEGV2 |= 0x04; // 1A位是1
if ((segmentCodes & 0x02) == 0) C1SEGV2 &= 0xfb; // 1B位是0
else C1SEGV2 |= 0x04; // 1B位是1
if ((segmentCodes & 0x04) == 0) C2SEGV2 &= 0xfb; // 1C位是0
else C2SEGV2 |= 0x04; // 1C位是1
if ((segmentCodes & 0x08) == 0) C3SEGV2 &= 0xfb; // 1D位是0
else C3SEGV2 |= 0x04; // 1D位是1
if ((segmentCodes & 0x10) == 0) C3SEGV2 &= 0xfd; // 1E位是0
else C3SEGV2 |= 0x02; // 1E位是1
if ((segmentCodes & 0x20) == 0) C1SEGV2 &= 0xfd; // 1F位是0
else C1SEGV2 |= 0x02; // 1F位是1
if ((segmentCodes & 0x40) == 0) C2SEGV2 &= 0xfd; // 1G位是0
else C2SEGV2 |= 0x02; // 1G位是1
//if ((segmentCodes & 0x08) == 0) // 1H位是0
// else // 1H位是1
//左起第二位,
if ((segmentCodes & 0x01) == 0) C0SEGV2 &= 0xef; // 2A位是0
else C0SEGV2 |= 0x10; // 2A位是1
if ((segmentCodes & 0x02) == 0) C1SEGV2 &= 0xef; // 2B位是0
else C1SEGV2 |= 0x10; // 2B位是1
if ((segmentCodes & 0x04) == 0) C2SEGV2 &= 0xef; // 2C位是0
else C2SEGV2 |= 0x10; // 2C位是1
if ((segmentCodes & 0x08) == 0) C3SEGV2 &= 0xef; // 2D位是0
else C3SEGV2 |= 0x10; // 2D位是1
if ((segmentCodes & 0x10) == 0) C3SEGV2 &= 0xf7; // 2E位是0
else C3SEGV2 |= 0x08; // 2E位是1
if ((segmentCodes & 0x20) == 0) C1SEGV2 &= 0xf7; // 2F位是0
else C1SEGV2 |= 0x08; // 2F位是1
if ((segmentCodes & 0x40) == 0) C2SEGV2 &= 0xf7; // 2G位是0
else C2SEGV2 |= 0x08; // 2G位是1
//if ((segmentCodes & 0x08) == 0) // 1H位是0
// else
//左起第二位,
if ((segmentCodes & 0x01) == 0) C0SEGV2 &= 0xbf; // 3A位是0
else C0SEGV2 |= 0x40; // 3A位是1
if ((segmentCodes & 0x02) == 0) C1SEGV2 &= 0xbf; // 3B位是0
else C1SEGV2 |= 0x40; // 3B位是1
if ((segmentCodes & 0x04) == 0) C2SEGV2 &= 0xbf; // 3C位是0
else C2SEGV2 |= 0x40; // 3C位是1
if ((segmentCodes & 0x08) == 0) C3SEGV2 &= 0xbf; // 3D位是0
else C3SEGV2 |= 0x40; // 3D位是1
if ((segmentCodes & 0x10) == 0) C3SEGV2 &= 0xdf; // 3E位是0
else C3SEGV2 |= 0x20; // 3E位是1
if ((segmentCodes & 0x20) == 0) C1SEGV2 &= 0xdf; // 3F位是0
else C1SEGV2 |= 0x20; // 3F位是1
if ((segmentCodes & 0x40) == 0) C2SEGV2 &= 0xdf; // 3G位是0
else C2SEGV2 |= 0x20; // 3G位是1
//if ((segmentCodes & 0x08) == 0) // 1H位是0
// else
*/
displayThreeDigits(i);
i++;
if(i>250)i=0;
if(ucshow>=0xFF)
{
ucshow=0x00;
// X32KCR = 0x00;
}
}
}
}
/********************* INT0中断函数 *************************/
void Ext_INT0 (void) interrupt 0
{
OpTime = 6;
}
/********************** LCD配置函数 *****************************/
void LCD_config(void)
{
// u8 i;
P_SW2 |= 0x80; // SFR enable
// X32KCR = 0x80 + 0x40; //启动外部32K晶振, 低增益+0x00, 高增益+0x40.
//P1n_pure_input(0xc0); //P1.6 P1.7设置为高阻输入
// P1IE = ~0xc0; //P1.6 P1.7关闭数字输入功能
// X32KCR = 0x80;
LCDCFG= 0xc0 + 7; // 0x00:选择CPU时钟为LCD时钟, 0x80: 选择外部32K晶振做时钟. VLCD电压选择0~7对应0.65+VLCD*0.05.
// LCDCFG|=0x07;
// X32KCR = 0x80 + 0x40; //启动外部32K晶振, 低增益+0x00, 高增益+0x40.
P1n_pure_input(0xc0); //P1.6 P1.7设置为高阻输入
P1IE = ~0xc0; //P1.6 P1.7关闭数字输入功能
X32KCR = 0x80;
DBLEN = 0; // 设置LCD显示时的死区时间长度, 取值0~7.
COMLENH = 0; // COM时间长度设置 高字节COMLEN,一共20bit.
COMLENM = 0; // COM时间长度设置 中字节COMLEN LCD刷新率 = LCD时钟频率 / ((DBLEN+COMLEN+1) *2 * COM数)
COMLENL = 65; // COM时间长度设置 低字节COMLEN LCD刷新率 = 32768/((2+65+1)*2*4) = 60Hz
BLINKRATE = 60; // 闪烁率配置寄存器, LCD闪烁率 = LCD刷新率 / BLINKRATE Hz
COMON= 0x0f; // COM使能寄存器
SEGON1 = 0x00; // SEG线使能寄存器1, SEG7~SEG0
SEGON2 = 0x00; // SEG线使能寄存器2, SEG15~SEG8
SEGON3 = 0x7e; // SEG线使能寄存器3, SEG23~SEG16
SEGON4 = 0x00; // SEG线使能寄存器4, SEG31~SEG24
SEGON5 = 0x00; // SEG线使能寄存器5, SEG39~SEG32
// P5n_pure_input(0x03); //P5.0 P5.1 设置为高阻输入 COM0 COM1
// P3n_pure_input(0x60); //P3.5 P3.6 设置为高阻输入 COM2 COM3
// P3M0 = 0x00; P3M1 = 0xFF;
// P5M0 = 0x00; P5M1 = 0xFF;
// P3DR = 0x00;
// P0DR = 0x00;
// LCDCFG2 = 0x0f; // SEG0~3切换到P7.7~7.4
// P7n_pure_input(0xf0); //P7.7~P7.4 设置为高阻输入 SEG0~SEG3 (对应P7.7~7.4)
// P4n_pure_input(0x80); //P4.7 设置为高阻输入 SEG4
// P1n_pure_input(0x03); //P1.1~P1.0 设置为高阻输入 SEG5 SEG6 (对应P1.1 P1.0)
// P0n_pure_input(0x60); //P0.7~P0.5 设置为高阻输入 SEG7 SEG8 SEG9(对应P0.7 P0.6 P0.5)
// P5n_pure_input(0x0C); //P5.3 P5.2 设置为高阻输入 SEG10 SEG11 (对应P5.3 P5.2)
// P0n_pure_input(0x1f); //P0.4~P0.0 设置为高阻输入 SEG12~SEG16(对应P0.4 ~ 0.0)
// P4n_pure_input(0x60); //P4.6 P4.5 设置为高阻输入 SEG17 SEG18
// P2n_pure_input(0xF0); //P2.7~P2.0 设置为高阻输入 SEG19~SEG26(对应P2.7~2.0)
// P2M0 = 0x00; P2M1 = 0xFF;
// P4M0 = 0x00; P4M1 = 0xFF;
// P2DR = 0x00;
// P4DR = 0x00;
// P4n_pure_input(0x1e); //P4.4~P4.1 设置为高阻输入 SEG27~SEG30(对应P4.4~4.1)
// P3n_pure_input(0x80); //P3.7 设置为高阻输入 SEG31
// P7n_pure_input(0x0f); //P7.3~P7.0 设置为高阻输入 SEG32~SEG35(对应P7.3~7.0)
// P6n_pure_input(0x0f); //P6.0~P6.3 设置为高阻输入 SEG36~SEG39(对应P6.3~6.0)
C0SEGV2 = 0x00;
C1SEGV2 = 0x00;
C2SEGV2 = 0x00;
C3SEGV2 = 0x00;
LCDCR = (0<<1) + 1; // LCD控制寄存器, 0:普通模式, 1:长暗模式, 2:长亮模式, 3:闪烁模式.+0:禁止LCD模块,+1:允许LCD模块.
}
//========================================================================
// 函数:u8 Timer0_Config(u32 reload)
// 描述: timer0初始化函数.
// 参数: reload: 重装值.
// 返回: 0: 初始化正确, 1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-3-5
//========================================================================
u8 Timer0_Config(u32 reload) //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us)
{
TR0 = 0; //停止计数
if(reload >= (65536UL * 12)) return 1; //值过大, 返回错误
if(reload < 65536UL) AUXR |= 0x80; //1T mode
else
{
AUXR &= ~0x80; //12T mode
reload = reload / 12;
}
reload = 65536UL - reload;
TH0 = (u8)(reload >> 8);
TL0 = (u8)(reload);
ET0 = 1; //允许中断
TMOD = (TMOD & ~0x03) | 0; //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
TR0 = 1; //开始运行
return 0;
}
//========================================================================
// 函数: void timer0_int (void) interrupt TIMER0_VECTOR
// 描述:timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2016-5-12
//========================================================================
void timer0_ISR (void) interrupt TIMER0_VECTOR
{
static u8 i;
B_20ms = 1; //20ms时隙标志
i++;
if(i>=5)
{
i=0;
uc0_5sflag=1;
// P37=!P37;
}
}
页:
[1]