用模塊廠家資料+豆包+自己修改生成的51單片機+2片HC595四位LED數(shù)碼管計數(shù)器C代碼,可實現(xiàn)點動增加或減小1,長按連續(xù)加1或連續(xù)減1。實際調(diào)試OK,在此分享給大家。
/*51單片機+2片HC595四位LED數(shù)碼管計數(shù)器C代碼*/
//11.0592MHz
//可實現(xiàn)點動增加或減小1,長按連續(xù)加1或連續(xù)減1.
#include <REG51.H>
#include <intrins.h> // 引入_nop_()函數(shù)頭文件
#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; //串行數(shù)據(jù)輸入
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; // 當前顯示的數(shù)位索引
// 調(diào)試用 LED 引腳定義
sbit DEBUG_LED = P3^7;
sbit KEY_DEBUG_LED = P3^6;
// 將計數(shù)值拆分成每一位并更新到LED數(shù)組中
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單字節(jié)串行移位函數(shù)
{
uchar i;
for(i = 8; i >= 1; i--)
{
if (X & 0x80)
DIO = 1;
else
DIO = 0;
X <<= 1;
SCLK = 0;
SCLK = 1;
}
}
// 延時函數(shù),單位為毫秒
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; // 增加按鍵延時計數(shù)
static uint down_key_delay_count = 0; // 減小按鍵延時計數(shù)
/* 加鍵處理 */
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; // 重置延時計數(shù)
}
else // 按鍵已按下
{
up_key_delay_count++;
if(up_key_delay_count >= 5) // 延時5次,可根據(jù)需要調(diào)整
{
count++;
if(count > 9999)
count = 9999;
up_key_delay_count = 0; // 重置延時計數(shù)
}
}
}
}
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; // 重置延時計數(shù)
}
else // 按鍵已按下
{
down_key_delay_count++;
if(down_key_delay_count >= 5) // 延時5次,可根據(jù)需要調(diào)整
{
if (count > 0) {
count--;
}
down_key_delay_count = 0; // 重置延時計數(shù)
}
}
}
}
else
{
down_key_pressed = 0; // 按鍵松開,清除標志
}
/* 清除鍵處理 */
if(CLE_KEY == 0)
{
delay_ms(20); // 消抖延時
if(CLE_KEY == 0)
{
count = 0; // 清零計數(shù)
update_LED(); // 及時更新顯示緩存
}
}
}
// 定時器0初始化函數(shù)
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中斷服務函數(shù)
void Timer0_ISR() interrupt 1
{
// 先聲明變量
unsigned char code *led_table;
uchar i;
// 重新加載初值
TH0 = (65536 - 2000) / 256;
TL0 = (65536 - 2000) % 256;
// 顯示當前數(shù)位
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;
}
// 主函數(shù)
void main()
{
count = 0;
update_LED();
Timer0_Init();
while (1)
{
key();
update_LED();
}
}
|