自己的一些平时积累,如有发现什么不足,还望指正。
1.定时器模块
对我而言,超声波我推荐用PCA测量,因为stc15单片机只有3个定时器,定时器0用于测量频率,而串口通信只能用定时器1和2,当然串口通信我觉得定时2好点,因为串口通信不需要高的优先级,所以还需要用一个定时器去规划所有时间。
2.超声波测距
unsigned int distance=0,distance_time=1;
bit distance_flag=0;
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初始值
TH1 = 0xD1; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA=1;//
ET1=1;
}
void Timer1_Service() interrupt 3{
if(++distance_time>=500){distance_time=1;distance_flag=1;}//也可以选200
}
void Delay12us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 33;
while (--i);
}
void Sonic_init(){
CMOD=0x00;//这个需要选系统时钟的12分之一,写CMOD=0x04为系统时钟,不对
CCON=0x00;
}
void Get_distance(){
uchar num123=8;
CH=0;
CL=0;
CF=0;
CR=1;
while(num123--){
P10=1;Delay12us();
P10=0;Delay12us();
}
while(!CF&&P11);
CR=0;
if(CF==1){
CF=0;
distance=255;//这个跟题意来
}
else{
distance=(uint)((CH*256+CL+156)*0.017);//距离上有接近3cm误差
}
}
void main(){
while(1){
if(distance_flag){distance_flag=0;Get_distance();}
}
}
3.频率测量
频率测量记得1s测一次,同时需要连接P34与SIGNAG,同时其由RB3控制。
unsigned int frequency=0,frequency_time=1;
bit frequency_flag=0;
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初始值
TH1 = 0xD1; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA=1;//
ET1=1;
}
void Timer1_Service() interrupt 3{
if(++frequency_time>=1000){frequency_time=1;frequency_flag=1;}//1秒
}
void Timer0Init(void) //微秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
// TMOD &= 0xF0; //设置定时器模式(改成计数)
TMOD |= 0x04; //设置定时器模式//改成计数模式
TL0 = 0x00; //设置定时初始值
TH0 = 0x00; //设置定时重载值
TF0 = 0; //清除TF0标志
}
void Timer0(){
TR0=0;
frequency=TH0*256+TL0;
TH0=0;
TL0=0;
TF0=0;
TR0=1;
}
void main(){
while(1){
if(frequency_flag){frequency_flag=0;Timer0();}
}
}
4.串口通信
#include <stdio.h>
#include <string.h>
unsigned char buffer[30]//范围根据输出或读入字符串大小设定
unsigned char rec_num=0,rec_time=1;
bit rec_flag=0,send_flag=0;
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初始值
TH1 = 0xD1; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA=1;//
ET1=1;
}
void Timer1_Service() interrupt 3{
if(rec_flag&&++rec_time>=50){//50ms限定时
rec_flag=0;
rec_time=1;
send_flag=1;
}
}
void UartInit(void) //9600bps@12.000MHz 注意波特率
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xC7; //设置定时初始值
T2H = 0xFE; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES=1;//打开串口中断
}
void Service_usart() interrupt 4{
if(RI){
RI=0;
buffer[rec_num++]=SBUF;
rec_flag=1;
}
}
void Send_date(uchar date){
SBUF=date;
while(!TI);
TI=0;
}
void Send_String(uchar *str){
while(*str)
Send_date(*str++);
}
void main(){
while(1){
//如果字符比较,之间比较相等就行,也不许要最后叫'\0',可直接if('A'==buffer[0]);
if(send_flag){//接受到字符串
send_flag=0;
buffer[rx_cnt]='\0';//等于\r\n
rx_cnt=0;
if(!strcmp("ST\r\n",buffer)){//比较是否相等
sprintf(buffer,"$%d,%d\r\n",20,0);//数值也可以是变量,将字符赋该buffer中
Send_String(buffer);
}
}
}
5.定时器2控制转机
定时器2的中断允许通过IE2控制,同时其中断函数编号为12。
unsigned char relay_num=0;
void Timer2Init(void) //200微秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xA0; //设置定时初始值
T2H = 0xF6; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2|=0x04;
}
void Timer2_service () interrupt 12{
uchar relay_true=0x00;
if(relay_num<=relay_now)
relay_true|=0x20;
else
relay_true&=0xdf;
relay_num=(relay_num+1)%5;
P0=relay_true;P2|=0xa0;P2&=0x1f;
}
这个在第13届国赛时考了
就是因为1kHz是1ms,所以不太好用你的定时器1进行调解,当你其实可以设置定时器1位200us的,然后其他时间同时改变就行,但多学一种方法也是好的。