用模块厂家资料+豆包+自己修改生成的51单片机+2片HC595四位LED数码管计数器C代码,可实现点动增加或减小1,长按连续加1或连续减1。实际调试OK,在此分享给大家。
/*51单片机+2片HC595四位LED数码管计数器C代码*/
//11.0592MHz
//可实现点动增加或减小1,长按连续加1或连续减1.
#include <REG51.H>
#include <intrins.h> // 引入_nop_()函数头文件
#define uchar unsigned char
#define uint unsigned int
unsigned char code LED_0F[] =
{// 0 1 2 3 4 5 6 7 8 9 A b C d E F -
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8C,0xBF,0xC6,0xA1,0x86,0xFF,0xbf
};
uint count;
static unsigned char key_delay = 0;
sbit DIO = P1^0; //串行数据输入
sbit RCLK = P1^1; //时钟脉冲信号——上升沿有效
sbit SCLK = P1^2; //打入信号————上升沿有效
sbit UP_KEY=P2^0; //增加按键
sbit DOWN_KEY=P2^1; //减小按键
sbit CLE_KEY=P2^2; //清零按键
uchar LED[8]; //用于LED的8位显示缓存
uchar display_index = 0; // 当前显示的数位索引
// 调试用 LED 引脚定义
sbit DEBUG_LED = P3^7;
sbit KEY_DEBUG_LED = P3^6;
// 将计数值拆分成每一位并更新到LED数组中
void update_LED()
{
LED[0] = count % 10; // 个位
LED[1] = (count % 100) / 10; // 十位
LED[2] = (count % 1000) / 100; // 百位
LED[3] = count / 1000; // 千位
}
void LED_OUT(uchar X) // LED单字节串行移位函数
{
uchar i;
for(i = 8; i >= 1; i--)
{
if (X & 0x80)
DIO = 1;
else
DIO = 0;
X <<= 1;
SCLK = 0;
SCLK = 1;
}
}
// 延时函数,单位为毫秒
void delay_ms(uint ms)
{
uint i, j;
for (i = 0; i < ms; i++)
{
for (j = 0; j < 123; j++)
{
_nop_();
}
}
}
void key()
{
static bit up_key_pressed = 0; // 增加按键按下标志
static bit down_key_pressed = 0; // 减小按键按下标志
static uint up_key_delay_count = 0; // 增加按键延时计数
static uint down_key_delay_count = 0; // 减小按键延时计数
/* 加键处理 */
if(UP_KEY == 0)
{
delay_ms(20); // 消抖延时
if(UP_KEY == 0)
{
if(!up_key_pressed) // 按键首次按下
{
count++;
if(count > 9999)
count = 9999;
up_key_pressed = 1; // 设置按键按下标志
up_key_delay_count = 0; // 重置延时计数
}
else // 按键已按下
{
up_key_delay_count++;
if(up_key_delay_count >= 5) // 延时5次,可根据需要调整
{
count++;
if(count > 9999)
count = 9999;
up_key_delay_count = 0; // 重置延时计数
}
}
}
}
else
{
up_key_pressed = 0; // 按键松开,清除标志
}
/* 减键处理 */
if(DOWN_KEY == 0)
{
delay_ms(20); // 消抖延时
if(DOWN_KEY == 0)
{
if(!down_key_pressed) // 按键首次按下
{
if (count > 0) {
count--;
}
down_key_pressed = 1; // 设置按键按下标志
down_key_delay_count = 0; // 重置延时计数
}
else // 按键已按下
{
down_key_delay_count++;
if(down_key_delay_count >= 5) // 延时5次,可根据需要调整
{
if (count > 0) {
count--;
}
down_key_delay_count = 0; // 重置延时计数
}
}
}
}
else
{
down_key_pressed = 0; // 按键松开,清除标志
}
/* 清除键处理 */
if(CLE_KEY == 0)
{
delay_ms(20); // 消抖延时
if(CLE_KEY == 0)
{
count = 0; // 清零计数
update_LED(); // 及时更新显示缓存
}
}
}
// 定时器0初始化函数
void Timer0_Init() {
TMOD |= 0x01; // 设置定时器0为模式1(16位定时器)
TH0 = (65536 - 2000) / 256; // 定时2ms
TL0 = (65536 - 2000) % 256;
ET0 = 1; // 使能定时器0中断
EA = 1; // 使能总中断
TR0 = 1; // 启动定时器0
}
// 定时器0中断服务函数
void Timer0_ISR() interrupt 1
{
// 先声明变量
unsigned char code *led_table;
uchar i;
// 重新加载初值
TH0 = (65536 - 2000) / 256;
TL0 = (65536 - 2000) % 256;
// 显示当前数位
led_table = LED_0F + LED[display_index];
i = *led_table;
LED_OUT(i);
switch (display_index)
{
case 0: LED_OUT(0x01); break;
case 1: LED_OUT(0x02); break;
case 2: LED_OUT(0x04); break;
case 3: LED_OUT(0x08); break;
}
RCLK = 0;
RCLK = 1;
// 更新显示索引
display_index = (display_index + 1) % 4;
}
// 主函数
void main()
{
count = 0;
update_LED();
Timer0_Init();
while (1)
{
key();
update_LED();
}
}
|