)
基于51单片机的T0计数器系统设计使用定时器0作为计数器对外部脉冲进行计数并通过数码管显示计数值。一、系统设计1.1 功能要求T0作为计数器对P3.4(T0)引脚的外部脉冲计数4位共阳数码管显示计数值0-9999支持加计数和减计数两种模式按键控制清零、模式切换、暂停/继续计数溢出处理0-9999循环计数频率可达50kHz1.2 硬件资源资源型号/规格数量单片机STC89C52/AT89C521数码管4位共阳数码管1按键轻触开关3电阻220Ω限流8电阻10kΩ上拉3晶振11.0592MHz1脉冲源按键/信号发生器1二、硬件设计2.1 电路原理图5V | - 数码管显示 | 段选P0.0-P0.7 (经220Ω电阻) | 位选P2.0-P2.3 (经220Ω电阻) | - 按键控制 | K1(清零) - P3.0 - GND | K2(模式) - P3.1 - GND | K3(暂停) - P3.2 - GND | (各接10kΩ上拉电阻到5V) | - 计数输入 | P3.4(T0) - 外部脉冲输入 | - 单片机最小系统 XTAL1/XTAL2 - 11.0592MHz晶振 RST - 10kΩ电阻10μF电容 EA - 5V VCC - 5V GND - GND2.2 引脚分配表单片机引脚连接设备功能说明P0.0-P0.7数码管段选a,b,c,d,e,f,g,dpP2.0-P2.3数码管位选千位、百位、十位、个位P3.0按键K1清零P3.1按键K2模式切换P3.2按键K3暂停/继续P3.4外部脉冲T0计数输入P1.0LED指示计数状态指示三、软件设计3.1 主程序 (main.c)#includereg52.h#includedisplay.h#includekeyboard.h#includetimer0_counter.h// 全局变量unsignedintcount_value0;// 当前计数值unsignedintmax_count9999;// 最大计数值unsignedintmin_count0;// 最小计数值bit count_mode0;// 0:加计数 1:减计数bit count_enable1;// 计数使能bit overflow_flag0;// 溢出标志voidmain(void){System_Init();while(1){Key_Process();// 按键处理Display_Update();// 显示更新Count_Check();// 计数范围检查}}voidSystem_Init(void){// 初始化定时器0为计数器模式Timer0_Counter_Init();// 初始化数码管Display_Init();// 显示初始值Display_Number(count_value);// 开启总中断EA1;// 启动计数TR01;}voidKey_Process(void){unsignedcharkeyKey_Scan();switch(key){caseKEY_CLEAR:// 清零count_value0;Display_Number(count_value);break;caseKEY_MODE:// 切换模式count_mode!count_mode;if(count_mode)Display_Show_Mode(DEC);// 显示减计数模式elseDisplay_Show_Mode(INC);// 显示加计数模式break;caseKEY_PAUSE:// 暂停/继续count_enable!count_enable;if(count_enable){TR01;// 继续计数P1_00;// LED亮表示计数中}else{TR00;// 暂停计数P1_01;// LED灭表示暂停}break;default:break;}}voidCount_Check(void){// 检查溢出if(overflow_flag){overflow_flag0;if(count_mode0)// 加计数溢出{count_valuemin_count;// 回到最小值}else// 减计数溢出{count_valuemax_count;// 回到最大值}Display_Number(count_value);}// 检查是否达到极限if(count_valuemax_countcount_mode0){count_enable0;// 禁止计数TR00;P1_01;// LED灭}if(count_valuemin_countcount_mode1){count_enable0;// 禁止计数TR00;P1_01;// LED灭}}// 定时器0中断服务程序计数器溢出中断voidTimer0_ISR(void)interrupt1{overflow_flag1;// 设置溢出标志// 根据计数模式更新计数值if(count_mode0)// 加计数{count_value;if(count_valuemax_count)count_valuemin_count;// 循环}else// 减计数{count_value--;if(count_valuemin_count)count_valuemax_count;// 循环}Display_Number(count_value);}3.2 定时器0计数器 (timer0_counter.h)#ifndef__TIMER0_COUNTER_H__#define__TIMER0_COUNTER_H__#includereg52.h// 函数声明voidTimer0_Counter_Init(void);voidTimer0_Start(void);voidTimer0_Stop(void);voidTimer0_Set_Value(unsignedintvalue);unsignedintTimer0_Get_Value(void);#endif3.3 定时器0计数器 (timer0_counter.c)#includetimer0_counter.hvoidTimer0_Counter_Init(void){// 设置T0为计数器模式工作方式116位计数TMOD0xF0;// 清除T0控制位TMOD|0x05;// 0000 0101: T0为计数器方式116位// 设置计数初值0TH00x00;TL00x00;// 允许T0中断ET01;// 启动T0由TR0控制TR00;// 先不启动}voidTimer0_Start(void){TR01;// 启动计数器}voidTimer0_Stop(void){TR00;// 停止计数器}voidTimer0_Set_Value(unsignedintvalue){TH0value8;// 高8位TL0value0xFF;// 低8位}unsignedintTimer0_Get_Value(void){unsignedintvalue;value(TH08)|TL0;returnvalue;}3.4 数码管显示 (display.h)#ifndef__DISPLAY_H__#define__DISPLAY_H__#includereg52.h// 数码管段码定义共阳#defineSEG_A0x01#defineSEG_B0x02#defineSEG_C0x04#defineSEG_D0x08#defineSEG_E0x10#defineSEG_F0x20#defineSEG_G0x40#defineSEG_DP0x80// 数字0-9段码表externunsignedcharcode SegCode[10];// 位选定义#defineDIGIT_1P2_0// 千位#defineDIGIT_2P2_1// 百位#defineDIGIT_3P2_2// 十位#defineDIGIT_4P2_3// 个位// 函数声明voidDisplay_Init(void);voidDisplay_Number(unsignedintnum);voidDisplay_Scan(unsignedcharpos);voidDisplay_Clear(void);voidDisplay_Show_Mode(char*mode);// 显示缓冲区externunsignedcharDisplay_Buffer[4];#endif3.5 数码管显示 (display.c)#includedisplay.h// 共阳数码管段码表0-9unsignedcharcode SegCode[10]{0xC0,// 0: 1100 00000xF9,// 1: 1111 10010xA4,// 2: 1010 01000xB0,// 3: 1011 00000x99,// 4: 1001 10010x92,// 5: 1001 00100x82,// 6: 1000 00100xF8,// 7: 1111 10000x80,// 8: 1000 00000x90// 9: 1001 0000};// 字母段码表unsignedcharcode LetterCode[26]{0x88,// A0x83,// b0xC6,// C0xA1,// d0x86,// E0x8E,// F0xC2,// G0x89,// H0xF9,// I0xF1,// J0xC7,// L0xC8,// M0xC1,// n0xC0,// O0x8C,// P0x98,// q0x92,// r0x87,// S0x83,// t0xC1,// u0x91,// v0xD1,// w0x89,// X0x49,// y0x90// Z};unsignedcharDisplay_Buffer[4]{0xC0,0xC0,0xC0,0xC0};voidDisplay_Init(void){P00xFF;// 段选全灭P20x0F;// 位选全灭}voidDisplay_Number(unsignedintnum){// 分解各位数字unsignedcharthousand,hundred,ten,unit;thousandnum/1000;hundred(num%1000)/100;ten(num%100)/10;unitnum%10;// 存储显示缓冲区Display_Buffer[0]SegCode[thousand];Display_Buffer[1]SegCode[hundred];Display_Buffer[2]SegCode[ten];Display_Buffer[3]SegCode[unit];}voidDisplay_Scan(unsignedcharpos){// 关闭所有位选P20x0F;// 送段码switch(pos){case0:// 千位DIGIT_10;// 选中千位P0Display_Buffer[0];break;case1:// 百位DIGIT_20;// 选中百位P0Display_Buffer[1];break;case2:// 十位DIGIT_30;// 选中十位P0Display_Buffer[2];break;case3:// 个位DIGIT_40;// 选中个位P0Display_Buffer[3];break;}}voidDisplay_Clear(void){P00xFF;// 段选全灭P20x0F;// 位选全灭}voidDisplay_Show_Mode(char*mode){// 显示模式标识if(mode[0]I)// INC{Display_Buffer[0]LetterCode[I-A];Display_Buffer[1]LetterCode[N-A];Display_Buffer[2]LetterCode[C-A];Display_Buffer[3]0xFF;// 熄灭}elseif(mode[0]D)// DEC{Display_Buffer[0]LetterCode[D-A];Display_Buffer[1]LetterCode[E-A];Display_Buffer[2]LetterCode[C-A];Display_Buffer[3]0xFF;// 熄灭}}3.6 键盘扫描 (keyboard.h)#ifndef__KEYBOARD_H__#define__KEYBOARD_H__#includereg52.h// 按键定义#defineKEY_CLEAR0x01#defineKEY_MODE0x02#defineKEY_PAUSE0x03#defineKEY_NONE0xFF// 按键端口定义sbit KEY_CLR_PINP3^0;sbit KEY_MOD_PINP3^1;sbit KEY_PAU_PINP3^2;// 函数声明voidKey_Init(void);unsignedcharKey_Scan(void);#endif3.7 键盘扫描 (keyboard.c)#includekeyboard.h#includedelay.hvoidKey_Init(void){// 按键端口初始化}unsignedcharKey_Scan(void){// 检测清零键if(KEY_CLR_PIN0){Delay_Ms(10);// 消抖if(KEY_CLR_PIN0){while(KEY_CLR_PIN0);// 等待按键释放returnKEY_CLEAR;}}// 检测模式键if(KEY_MOD_PIN0){Delay_Ms(10);if(KEY_MOD_PIN0){while(KEY_MOD_PIN0);returnKEY_MODE;}}// 检测暂停键if(KEY_PAU_PIN0){Delay_Ms(10);if(KEY_PAU_PIN0){while(KEY_PAU_PIN0);returnKEY_PAUSE;}}returnKEY_NONE;}3.8 延时函数 (delay.h)#ifndef__DELAY_H__#define__DELAY_H__#includereg52.h// 函数声明voidDelay_Ms(unsignedintms);voidDelay_Us(unsignedintus);#endif3.9 延时函数 (delay.c)#includedelay.h// 毫秒延时voidDelay_Ms(unsignedintms){unsignedinti,j;for(ims;i0;i--)for(j110;j0;j--);}// 微秒延时voidDelay_Us(unsignedintus){while(us--){_nop_();_nop_();_nop_();_nop_();}}四、Proteus仿真电路4.1 Proteus元件清单1. AT89C52 (单片机) 2. 7SEG-MPX4-CA (4位共阳数码管) 3. BUTTON (按键×3) 4. RES (电阻220Ω×8) 5. RES (电阻10kΩ×3) 6. CRYSTAL (11.0592MHz) 7. CAP (电容30pF×2) 8. POWER (电源) 9. GROUND (地) 10. SIGNAL_GENERATOR (信号发生器用于产生脉冲)4.2 仿真连接图AT89C52: P0.0-P0.7 - 数码管段选a-g,dp P2.0-P2.3 - 数码管位选1-4 P3.0 - 按键K1(清零) P3.1 - 按键K2(模式) P3.2 - 按键K3(暂停) P3.4 - 信号发生器输出T0计数输入 XTAL1/XTAL2 - 11.0592MHz晶振 RST - 10kΩ电阻10μF电容 VCC - 5V GND - GND五、功能扩展5.1 增加计数频率测量// 测量计数频率voidMeasure_Frequency(void){staticunsignedintlast_count0;staticunsignedlonglast_time0;unsignedintcurrent_count;unsignedlongcurrent_time;unsignedintfrequency;current_timeGet_System_Time();// 获取系统时间mscurrent_countTimer0_Get_Value();if(current_time-last_time1000)// 每秒测量一次{frequencycurrent_count-last_count;last_countcurrent_count;last_timecurrent_time;// 显示频率Display_Frequency(frequency);}}5.2 增加计数预置值// 设置预置值voidSet_Preset_Value(unsignedintpreset){count_valuepreset;Timer0_Set_Value(preset);Display_Number(count_value);}5.3 增加串行通信// 串口初始化voidUART_Init(void){TMOD0x0F;// 清除T1控制位TMOD|0x20;// 设置T1为模式28位自动重载TH10xFD;// 波特率9600TL10xFD;TR11;// 启动T1SM00;// 设置串口为模式1SM11;REN1;// 允许接收EA1;// 允许总中断ES1;// 允许串口中断}// 串口中断服务程序voidUART_ISR(void)interrupt4{unsignedcharreceived_data;if(RI)// 接收中断{RI0;// 清除接收中断标志received_dataSBUF;// 根据接收到的数据设置预置值if(received_data0received_data9){unsignedintdigitreceived_data-0;count_valuecount_value*10digit;if(count_value9999)count_value9999;Display_Number(count_value);}elseif(received_dataC||received_datac){count_value0;Display_Number(count_value);}}}参考代码 数码管T0计数器设计www.youwenfan.com/contentcsv/118036.html六、使用说明6.1 操作步骤接通5V电源数码管显示初始值0000将脉冲源连接到P3.4(T0)引脚按模式键切换加/减计数模式按暂停键暂停/继续计数按清零键将计数值清零6.2 注意事项外部脉冲幅度需在0-5V之间脉冲宽度需大于2个机器周期最大计数频率不超过50kHz计数溢出时会自动循环6.3 调试技巧先用按键模拟脉冲测试基本功能再用信号发生器测试高频计数观察LED指示灯判断计数状态使用示波器观察T0引脚波形七、性能指标参数指标计数范围0-9999计数模式加计数/减计数最大计数频率50kHz显示方式4位静态显示按键响应50ms功耗50mA 5V