准备工作
使用ne555模块时,需要将开发板最右边J3排母上的P34和NET_SIG用跳帽短接。
频率测定原理
ne555模块用到了定时器0的计数器模式,对ne555输出的脉冲进行计数。
计数器可以利用stc-isp软件生成的代码进行修改。
定时器修改
生成定时器代码
修改定时器为定时器0,生成即可。
修改寄存器
void Timer0_Init(void) //100微秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x50; //设置定时初始值
TH0 = 0xFB; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
对于这段代码,我们需要修改AUXR、TMOD、TH1、TL1。
因为计数器不需要时钟,所以我们需要删除 AUXR |= 0X40;
通过查看stc官方数据手册可知
TMOD寄存器中的低四位是用来控制定时器0的模式的,我们需要将TMOD.1/TMOD.0置为01,将TMOD.2置为0。
即在 TMOD &= 0xf0; 后添加TMOD |= 0x05;
清空计数器
将TH0和TL0都给清零。
关闭中断
在代码最后加上 ET0 = 0;
最终代码
不要管注释,修改之后注释是错的
void Timer0_Init(void) //100微秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05;
TL0 = 0x00; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 0;
}
读取频率值
读取计数器
uint16 get_count()
{
uint16 count_tmp = TH0 << 8 | TL0; // 读取计数器的值
TL0 = 0x00; // 设置计数初始值
TH0 = 0x00; // 设置计数初始值
if (TF0) // 如果检测到定时器0溢出过,证明频率超过了65535,返回65535
return 0xffff;
else // 否侧返回计数器的值
return count_tmp;
}
设置定时器
大部分题目都会要求读取每秒的频率,设置一个定时器,进行计时,每秒读取一次即可。
代码
main.c
#include "reg52.h"
#include "seg.h"
typedef unsigned int uint16;
typedef unsigned char uint8;
sfr AUXR = 0x8e;
uint16 count = 0;
void Timer0_Init(void) //计数器0初始化
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05; //设置定时器模式
TL0 = 0x00; //设置计数初始值
TH0 = 0x00; //设置计数初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //允许计数器计数
ET0 = 0; //禁止计数器中断
}
void Timer1_Init(void) //2毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x40; //设置定时初始值
TH1 = 0xA2; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
}
uint16 get_count()
{
uint16 count_tmp = TH0 << 8 | TL0;
TL0 = 0x00; // 设置定时初始值
TH0 = 0x00; // 设置定时初始值
if (TF0)
return 0xffff;
else
return count_tmp;
}
void main()
{
Timer0_Init();
Timer1_Init();
EA = 1;
while(1);
}
uint16 timer1_2ms = 0;
void Timer1_Isr(void) interrupt 3
{
seg_server();
timer1_2ms = (timer1_2ms + 1) % 500;
if(timer1_2ms == 0)
{
count = get_count();
seg_buff[0] = seg_value[count/10000%10];
seg_buff[1] = seg_value[count/1000%10];
seg_buff[2] = seg_value[count/100%10];
seg_buff[3] = seg_value[count/10%10];
seg_buff[4] = seg_value[count%10];
}
}
seg.c
#include "reg52.h"
unsigned char seg_buff[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
unsigned char seg_value[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char seg_com = 0;
void seg_server()
{
P0 = 1<<seg_com;
P2 = P2 & 0x1f | 0xc0;
P2 &= 0x1f;
P0 = 0xff;
P2 = P2 & 0x1f | 0xe0;
P2 &= 0x1f;
seg_com = (seg_com + 1)%8;
P0 = 1<<seg_com;
P2 = P2 & 0x1f | 0xc0;
P2 &= 0x1f;
P0 = seg_buff[seg_com];
P2 = P2 & 0x1f | 0xe0;
P2 &= 0x1f;
}
seg.h
#ifndef _SEG_H_
#define _SEG_H_
extern unsigned char seg_buff[8];
extern unsigned char seg_value[];
void seg_server();
#endif
效果展示
由于身边没有开发板,就用了软件仿真。
注意事项
使用ne555模块时,由于ne555采用P34引脚记录脉冲,矩阵按键中第四列也是使用P34引脚。所以矩阵按键中的第四列,即s16、s17、s18、s19这四个按键是无法使用的。
当试题中同时出现矩阵按键和ne555时,矩阵按键用几列写几列,否则有概率会导致ne555和按键都出现问题。(ps:有的人矩阵按键不管用几个都要把16个按键都写一遍,问就是踩过坑)
注:矩阵按键第四列和ne555是不会一起考的。