用模块资料+豆包AI+自己修改生成的C代码,调试OK,奉献给大家
TM1650 4KEY4LED计数器(总减+移位+减1+加1)C代码
//TM1650四按键四数码管数据调整实验OK
//功能:按TM1650四按键四LED数码管模块第二个键,个位闪烁,第三个键减小,第四个键增大。十位以上以此类推。
//第一个按键为4位LED总显示数值递减计数
//主程序
#include<reg52.h>
#include<intrins.h>
#include"tm1650.h"
#define uchar unsigned char
#define uint unsigned int
// 新增全局变量声明
bit flash_flag; // 闪烁标志
uchar flash_counter; // 闪烁计时器
uchar adjust_mode = 0; // 新增调整模式状态
uchar digits[4] = {0,0,0,0}; // 新增数值存储数组
uint combined_value; // 4位LED显示总数值
// 显示编码表(带小数点控制位)
uchar CODE[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
// 定时器初始化(新增完整函数)
void Timer0_Init() {
TMOD |= 0x01; // 模式1
TL0 = 0x18; // 1ms定时
TH0 = 0xFC;
ET0 = 1; // 中断使能
TR0 = 1;
EA = 1;
}
// 定时器中断服务(新增完整实现)
void Timer0_ISR() interrupt 1
{
static uint counter = 0;
TH0 = 0xFC; // 重装初值
TL0 = 0x18;
if(++counter >= 500) { // 500ms周期
flash_flag = !flash_flag;
counter = 0;
}
}
// 显示更新函数(优化小数点处理)
void Update_Display()
{
uchar seg_data;
// 千位(地址0x68)
seg_data = (adjust_mode==4 && flash_flag) ? 0x00 : CODE[digits[0]];
TM1650_Set(0x68, seg_data | (adjust_mode==4 ? 0x80 : 0x00));
// 百位(地址0x6A)
seg_data = (adjust_mode==3 && flash_flag) ? 0x00 : CODE[digits[1]];
TM1650_Set(0x6A, seg_data | (adjust_mode==3 ? 0x80 : 0x00));
// 十位(地址0x6C)
seg_data = (adjust_mode==2 && flash_flag) ? 0x00 : CODE[digits[2]];
TM1650_Set(0x6C, seg_data | (adjust_mode==2 ? 0x80 : 0x00));
// 个位(地址0x6E)
seg_data = (adjust_mode==1 && flash_flag) ? 0x00 : CODE[digits[3]];
TM1650_Set(0x6E, seg_data | (adjust_mode==1 ? 0x80 : 0x00));
// 计算总数值
combined_value = digits[0] * 1000 + digits[1] * 100 + digits[2] * 10 + digits[3];
}
// 按键处理(增加边界保护)
void Process_Key(uchar key)
{
static uchar last_key = 0;
if(key == last_key) return;
// 模式切换键处理
if(key == 0x54) // 0x54是TM1650的按键代码之一
{
adjust_mode = (adjust_mode < 4) ? adjust_mode+1 : 0;
flash_flag = 0; // 强制显示稳定
}
if(key == 0x5c) // 0x5c是TM1650的按键代码之一
{
if(combined_value > 0) {
combined_value--;
// 将总数值拆分为各个数位
digits[0] = combined_value / 1000;
digits[1] = (combined_value / 100) % 10;
digits[2] = (combined_value / 10) % 10;
digits[3] = combined_value % 10;
}
}
// 数值调整(带范围限制)
if(adjust_mode > 0)
{
uchar *p = &digits[4 - adjust_mode];
if(key == 0x4C) *p = (*p - 1 + 10) % 10; // 循环减,0x4c是TM1650的按键代码之一
if(key == 0x44) *p = (*p + 1) % 10; // 循环加,0x44是TM1650的按键代码之一
}
last_key = key;
}
// 主函数(修正初始化逻辑)
void main()
{
Timer0_Init();
TM1650_Set(0x48, 0x51); // 显示控制:5级亮度
Update_Display(); // 初始化显示
while(1)
{
Process_Key(Scan_Key());
Update_Display();
}
}
//TM1650 C文件
#include<reg52.h>
#include"tm1650.h"
void Delay_us(uint i) //us延时
{
for(;i>0;i--)
{
_nop_();
// _nop_();
// _nop_();
// _nop_();
// _nop_();
}
}
void I2CStart(void) //开始信号
{
CLK_H;
DIO_H;
Delay_us(5);
DIO_L;
}
void I2Cask(void) //ACK信号
{
uchar timeout = 1;
CLK_H;
Delay_us(5);
CLK_L;
while((DIO)&&(timeout<=100))
{
timeout++;
}
Delay_us(5);
CLK_L;
}
void I2CStop(void) //停止信号
{
CLK_H;
DIO_L;
Delay_us(5);
DIO_H;
}
void I2CWrByte(uchar oneByte) //写一个字节高位在前,低位在后
{
uchar i;
CLK_L;
Delay_us(1);
for(i=0;i<8;i++)
{
oneByte = oneByte<<1;
DIO = CY;
CLK_L;
Delay_us(5);
CLK_H;
Delay_us(5);
CLK_L;
}
}
uchar Scan_Key(void) // 按键扫描
{
uchar i;
uchar rekey;
I2CStart();
I2CWrByte(0x49);//读按键命令
I2Cask();
//DIO_H;
for(i=0;i<8;i++)
{
CLK_H;
rekey = rekey<<1;
if(DIO)
{
rekey++;
}
Delay_us(5);
CLK_L;
}
I2Cask();
I2CStop();
return(rekey);
}
void TM1650_Set(uchar add,uchar dat) //数码管显示
{
//写显存必须从高地址开始写
I2CStart();
I2CWrByte(add); //第一个显存地址
I2Cask();
I2CWrByte(dat);
I2Cask();
I2CStop();
}
//TM1650 C文件
#ifndef __TM1650_H__
#define __TM1650_H__
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit CLK = P1^0;
sbit DIO = P1^1;
#include<reg52.h>
#define CLK_H CLK = 1
#define CLK_L CLK = 0
#define DIO_H DIO = 1
#define DIO_L DIO = 0
void TM1650_Set(uchar add,uchar dat);
uchar Scan_Key(void);
#endif
|