基于STC系列单片机实现定时器扫描数码管显示定时器/计数器产生频率的功能

javascript 复制代码
#define uchar unsigned char//自定义无符号字符型为uchar
#define uint unsigned int//自定义无符号整数型为uint
#define NixieTubeSegmentCode P0//自定义数码管段码为单片机P0组引脚
#define NixieTubeBitCode P2//自定义数码管位码为单片机P2组引脚
sbit LED P1^0;//位定义LED灯为单片机P1.0脚
uchar Code NixieTubeBitCodeArray = [0xfe,0xfd,0xfb,0xf7];//定义数码管位码数组变量
uchar NixieTubeDisplayDataArray[0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00];//定义数码管显示0~F数据及符号"---"及熄灭数组变量
uchar NixieTubeCacheDataArray[] = [16,16,16,16];//定义数码管缓存数据数组变量
//uchar NixieTubeBootTimerFlag = 1;//定义数码管开机时间标志位变量
uint KeyPressNumber;//声明按键按下数值变量
//uint NixieTubeBootTimer = 0;//定义数码管开机时间变量
uint Timer0TimeCount;//声明定时器0定时计数变量
//void NixieTubeBootDisplay();//数码管开机显示函数
void NixieTubeDisplayDataSplit();//数码管显示数据分解函数
void NixieTubeDisplayData();//数码管显示数据函数
void Timer0Init(void);//定时器0初始化函数
void Timer1Init(void);//定时器1初始化函数 
  void main(void)//主函数
{
   Timer0Init();//定时器0初始化函数 
   Timer1Init();//定时器1初始化函数 
   //NixieTubeBootDisplay();//数码管开机显示函数
   while(1)//主循环
  {
    NixieTubeDisplayDataSplit();//数码管显示数据分解函数
   }
  }
  /*****void NixieTubeBootDisplay();//数码管开机显示函数
 {
   do
  {
    if(NixieTubeBootTimer = 1000 )//如果数码管开机时间等于1s
    LED = ~ LED;//LED灯亮灭更新
   }while(NixieTubeBootTimer < 5000);//当数码管开机时间小于5s
   NixieTubeBootTimerFlag = 0;//数码管开机时间标志位清0
   LED = 1;//LED灯熄灭
  }*****/
  void NixieTubeDisplayDataSplit()//数码管显示数据分解函数
 {
   NixieTubeCacheDataArray[0] = KeyPressNumber / 1000;//数码管千位数据显示
   NixieTubeCacheDataArray[1] = KeyPressNumber / 100 % 10;//数码管百位数据显示
   NixieTubeCacheDataArray[2] = KeyPressNumber / 10 % 10;//数码管十位数据显示
   NixieTubeCacheDataArray[3] = KeyPressNumber % 10;//数码管个位数据显示
  }
  void NixieTubeDisplayData()//数码管显示数据函数  
 {  
   static uchar i = 0;//定义静态数码管位变化变量
   switch(i)//数码管位变化筛选
  {
    case 0 ://数码管千位显示
            NixieTubeSegmentCode = 0x00;//数码管段码消影
            NixieTubeSegmentCode = NixieTubeDisplayDataArray[NixieTubeCacheDataArray[0]];//数码管千位的段码显示
            NixieTubeBitCode = NixieTubeBitCodeArray[0];//数码管千位码显示
            i++;//数码管位变化自加1
            break;//跳出
    case 1 ://数码管百位显示
            NixieTubeSegmentCode = 0x00;//数码管段码消影
            NixieTubeSegmentCode = NixieTubeDisplayDataArray[NixieTubeCacheDataArray[1]];//数码管百位的段码显示
            NixieTubeBitCode = NixieTubeBitCodeArray[1];//数码管百位码显示
            i++;//数码管位变化自加1
            break;//跳出 
    case 2 ://数码管十位显示
            NixieTubeSegmentCode = 0x00;//数码管段码消影
            NixieTubeSegmentCode = NixieTubeDisplayDataArray[NixieTubeCacheDataArray[2]];//数码管十位的段码显示
            NixieTubeBitCode = NixieTubeBitCodeArray[2];//数码管十位码显示
            i++;//数码管位变化自加1
            break;//跳出
    case 3 ://数码管个位显示
            NixieTubeSegmentCode = 0x00;//数码管段码消影
            NixieTubeSegmentCode = NixieTubeDisplayDataArray[NixieTubeCacheDataArray[3]];//数码管个位的段码显示
            NixieTubeBitCode = NixieTubeBitCodeArray[3];//数码管个位码显示
            i = 0;//数码管位变化清0
            break;//跳出
    default:break;//跳出
   }
  }
  /*****关于8051系列单片机定时器初值(定时计数初值)计算的知识点*****/
  /****
  时钟周期(又称振荡周期):单片机晶振频率的倒数 例:单片机晶振频率12MHz 则时钟周期=[1/(12*10^6)Hz]s=0.000000083s=0.000083ms=0.083us
  机器周期:单片机执行一条指令过程中需要完成一个基本操作(如:取指、译码、执行等基本操作)所需的时间 8051系列单片机的一个机器周期由6个S周期(状态周期)组成 一个时钟周期定义为一个节拍(用P表示) 二个节拍定义为一个状态周期(用S表示) 那么8051单片机的机器周期由6个状态周期组成 也就是说一个机器周期=6个状态周期=12个时钟周期=[12x[1/(12*10^6)Hz]s]s=0.000001s=0.001ms=1us
  指令周期:单片机取出一条指令且执行完这条指令所需的时间
  以上三者间的关系:指令周期>机器周期>时钟周期
  8051系列单片机定时器初值(定时计数初值)计算步骤如下(以单片机晶振频率为12MHz 定时器0工作模式为16位定时模式1 需要定时1ms来计算):
  1、一个机器周期=12个时钟周期=12乘以单片机晶振频率的倒数=12*[1/(12*10^6)Hz]s=0.000001s=0.001ms=1us
  2、定时时间=定时计数*一个机器周期 1ms=定时计数*1us 定时计数=1ms/1us=1000us/1us=1000次
  3、定时器初值(定时计数初值)=2^n-定时计数 n为几位定时器 此处n=16 则定时器初值(定时计数初值)=2^16-1000=65536-1000=64536 把64536转化成十六进制 拆开成高八位和低八位 高八位放TH0=0xfc或(65536-64536)/256 低八位放TL0=0x18或(65536-64536)%256
  4、综合公式:定时器初值(定时计数初值)=2^n-(晶振频率/几分频/定时频率) n为几位定时器 该公式常用于脉冲宽度调制中运算 例如:利用8051系列单片机晶振频率为12MHz的定时器0的16位定时模式1来产生1KHz方波脉冲 由此可知:定时时间=1/定时频率=1/1000Hz=0.001s=1ms=1000us 进而可得:定时器初值(定时计数初值)=2^n-(晶振频率/几分频/定时频率)=2^16-(12MHz/12/1KHz)=2^16-(12*10^6)Hz/12/1000Hz)=65536-1000=64536 把64536转化成十六进制 拆开成高八位和低八位 高八位放TH0=0xfc或(65536-64536)/256或Value >> 8 低八位放TL0=0x18或(65536-64536)%256或=Value 
  5、TH0 = Value >> 8;TL0 = Value;该两句代码解释如下:
  (1)、TH0 = Value >> 8相当于TH0 = (65536-10000)/256=55536/256=216.9375 分析:65536-10000=55536转化成二进制为11011000 11110000 55536/256=216.9375转化成二进制为11011000 由此可看出Value为(65536-10000)=55536的二进制数11011000 11110000右移8位就可以得到55536/256=216.9375的二进制数11011000
  (2)、TL0 = Value相当于TL0 = (65536-10000)%256=55536%256=240 分析:65536-10000=55536转化成二进制为11011000 11110000 55536%256=240转化成二进制为11110000 由此可看出Value为(65536-10000)=55536的二进制数11011000 11110000取低8位就可以得到55536%256=240的二进制数11110000
  ****/
  void Timer0Init(void)//定时器0定时1ms初始化函数 晶振为12MHz
 {
   TMOD &= 0xf0;//设定定时器/计数器工作模式清0
   TMOD |= 0x01;//设定定时器/计数器为定时器 工作模式为16位定时器0模式1
   TH0 = 0xfc;//设定定时器0高8位初值 
   TL0 = 0x18;//设定定时器0低8位初值
   TF0 = 0;//定时器0溢出中断标志位清0
   ET0 = 1;//打开定时器中断开关
   EA = 1;//打开定时器中断总开关
   TR0 = 1//打开定时器0开关
  } 
  void Timer1Init(void)//定时器1计数初始化函数 晶振为12MHz
 {
   TMOD &= 0x0f;//设定定时器/计数器工作模式清0
   TMOD |= 0x50;//设定定时器/计数器为计数器 工作模式为16位计数器1模式1
   TH1 = 0;//设定定时器1计数高8位初值
   TL1 = 0;//设定定时器1计数低8位初值
   TF1 = 0;//定时器1溢出中断标志位清0
   ET1 = 1;//打开定时器1中断开关
   EA = 1;//打开定时器中断总开关
   TR1 = 1//打开定时器1开关
  } 
  void Timer0(void) interrupt 1//定时器0定时1ms中断函数 晶振为12MHz
 {
   TR0 = 0;//关定时器0开关
   Timer0TimeCount++;//定时器0定时计数自加
   if(Timer0TimeCount >= 1000)//1s时间到
  {
    TR1 = 0;//关闭定时器1开关
    Timer0TimeCount = 0;//定时器0定时计数清0
    KeyPressNumber = TH1 * 256 + TL1;//把单片机定时器1引脚P3.5产生的脉冲总数赋给按键按下数值变量
    TH1 = 0;//定时器1计数高8位清0
    TL1 = 0;//定时器1计数低8位清0
    TR1 = 1;//打开定时器1开关
   }
   /*****if(NixieTubeBootTimerFlag == 1)//数码管开机时间标志位置1
  {
    NixieTubeBootTimer++;//数码管开机时间自加
   }*****/
   NixieTubeDisplayData();//数码管显示数据函数
   TH0 = 0xfc;//设定定时器0高8位初值
   TL0 = 0x18;//设定定时器0低8位初值
   TR0 = 1;//开定时器0开关
  }
相关推荐
wenchm2 小时前
细说STM32单片机DMA中断收发RTC实时时间并改善其鲁棒性的另一种方法
stm32·单片机·嵌入式硬件
茶猫_3 小时前
力扣面试题 - 25 二进制数转字符串
c语言·算法·leetcode·职场和发展
编码追梦人3 小时前
如何实现单片机的安全启动和安全固件更新
单片机
电子工程师UP学堂4 小时前
电子应用设计方案-16:智能闹钟系统方案设计
单片机·嵌入式硬件
ö Constancy4 小时前
Linux 使用gdb调试core文件
linux·c语言·vim
lb36363636364 小时前
介绍一下strncmp(c基础)
c语言·知识点
wellnw4 小时前
[linux] linux c实现共享内存读写操作
linux·c语言
blessing。。5 小时前
I2C学习
linux·单片机·嵌入式硬件·嵌入式
嵌新程7 小时前
day03(单片机高级)RTOS
stm32·单片机·嵌入式硬件·freertos·rtos·u575
珹洺7 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode