注意:超声波:用定时器1的12T模式 16位不可重装模式
main.c
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "iic.h"
code unsigned char Seg_Table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char smg[8];
//三个半小时
//参数
unsigned char fram_freq=90; //9.0KHZ 1.0-12.0
unsigned char fram_west=40; //10%-60%
unsigned char fram_dist=6; //0.6m 0.1-1.2
typedef struct
{
unsigned char b1:1;
unsigned char b2:1;
unsigned char b3:1;
unsigned char b4:1;
unsigned char b5:1;
unsigned char b6:1;
unsigned char b7:1;
unsigned char b8:1;
}Bits;
typedef union
{
unsigned char Hex;
Bits B;
}HextoB;
HextoB led_ctrl;
void vDevice_Process(unsigned char p2dat,unsigned char p0dat)
{
P0 = p0dat;
P2 = (P2&0x1f)|p2dat;
P2 = P2&0x1f;
}
//----------定时器
void Timer2Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x50; //设置定时初值
T2H = 0xFB; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04;
EA=1;
}
void Timer0Init(void) //1毫秒@12.000MHz
{
TMOD |= 0x05; //设置定时器模式
TL0 = 0; //设置定时初值
TH0 = 0; //设置定时初值
TR0 = 1; //定时器0开始计时
}
void Timer1Init(void) //1微秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0xFF; //设置定时初值
TH1 = 0xFF; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
}
//-----------测频率
unsigned int cnt_freq;
unsigned int freq;
unsigned int freq_khz;
void vGet_freq()
{
if(cnt_freq>=1000)
{
cnt_freq=0;
freq = (TH0<<8)|TL0;
TH0=0;TL0=0;
freq_khz = freq/1000.0f*10; //注意对较大的数如何保留小数,如果先乘10会超出65535范围出现错误。应该先除以浮点数再乘10就是保留了小数点一位
}
}
//-----脉冲输出
unsigned char pwm_num=8;//占空比
unsigned char pwm;
void vPWM_out()
{
if(freq_khz>fram_freq)
{
if(pwm<8)
{
vDevice_Process(0xa0,0x20);
}
else if(pwm<10)
{
vDevice_Process(0xa0,0x00);
}
else
{
pwm=0;
}
}
if(freq_khz<fram_freq)
{
if(pwm<2)
{
vDevice_Process(0xa0,0x20);
}
else if(pwm<10)
{
vDevice_Process(0xa0,0x00);
}
else
{
pwm=0;
}
}
}
//----------测湿度 RB2
unsigned char cnt_rb2;
unsigned char west; //湿度
unsigned char rb2;
void vGet_west()
{
if(cnt_rb2>=100)
{
cnt_rb2=0;
EA=0;
rb2 = Read_rb2();//电压转为0-100范围 100对应5V,即可用电压值表示湿度
EA=1;
west = rb2;
if(west>=100) west=99; //因为用两位数码管显示,所以最大时是99
}
}
//---------DAC输出 与湿度有关
void vDAC_Process()
{
if(west<=fram_west) Out_DAC(58); //1V 1V转折点是湿度参数
else if(west<80) Out_DAC(58+230/(80.0f-fram_west)*(west-fram_west));
else if(west>80) Out_DAC(255);
}
//----------超声波测距//12T的16位不可重装模式才准
void vSend_wave()
{
unsigned char i,j;
for(i=0;i<8;i++)
{
P10=1;
for(j=0;j<25;j++)
_nop_();
P10=0;
for(j=0;j<25;j++)
_nop_();
}
}
unsigned int vRecive_wave()
{
unsigned int dat;
TH1=0;TL1=0;
vSend_wave();
TR1=1;
while((P11==1)&&(TF1==0));
TR1=0;
if(TF1==1)
{
TF1=0;
dat = 999;
}
else
{
dat = ((TH1<<8)|TL1)*0.0175;
}
return dat;
}
unsigned char cnt_dist;
unsigned int dist;
unsigned char state_RELAY=0; //0断开 1闭合
unsigned char cnt_RELAY=0; //闭合次数统计
void vGet_dist()
{
if(cnt_dist>=100)
{
cnt_dist=0;
dist = vRecive_wave();
}
}
//----------数码管
unsigned char mode1=0; //mode1 频率 湿度 测距 参数 mode2
unsigned char mode_freq=0,mode_dist=0,mode_set=0;
void vSmg_Process()
{
if(mode1==0)//频率界面
{
unsigned int dat;
if(mode_freq==0)dat=freq;
else dat=freq_khz;
smg[0]=0x8e;
smg[1]=0xff;
smg[2]=Seg_Table[dat/100000];
smg[3]=Seg_Table[dat/10000%10];
smg[4]=Seg_Table[dat/1000%10];
smg[5]=Seg_Table[dat/100%10];
if(mode_freq==0)smg[6]=Seg_Table[dat/10%10];
else smg[6]=Seg_Table[dat/10%10]&0x7f;
smg[7]=Seg_Table[dat%10];
}
if(mode1==1)//湿度界面
{
smg[0]=0x89;
smg[1]=0xff;
smg[2]=0xff;
smg[3]=0xff;
smg[4]=0xff;
smg[5]=0xff;
smg[6]=Seg_Table[west/10];
smg[7]=Seg_Table[west%10];
}
if(mode1==2)//测距界面
{
if(mode_dist==0)
{
smg[0]=0x88;
smg[1]=0xff;
smg[2]=0xff;
smg[3]=0xff;
smg[4]=0xff;
if(dist>=100)smg[5]=Seg_Table[dist/100];
else smg[5]=0xff;
if(dist>=10)smg[6]=Seg_Table[dist/10%10];
else smg[6]=0xff;
smg[7]=Seg_Table[dist%10];
}
else if(mode_dist==1)
{
smg[0]=0x88;
smg[1]=0xff;
smg[2]=0xff;
smg[3]=0xff;
smg[4]=0xff;
smg[5]=Seg_Table[dist/100]&0x7f;
smg[6]=Seg_Table[dist/10%10];
smg[7]=Seg_Table[dist%10];
}
}
if(mode1==3)//参数界面
{
if(mode_set==0)//频率参数
{
smg[0]=0x8c;
smg[1]=Seg_Table[1];
smg[2]=0xff;
smg[3]=0xff;
smg[4]=0xff;
if(fram_freq>=100)smg[5]=Seg_Table[fram_freq/100];
else smg[5]=0xff;
smg[6]=Seg_Table[fram_freq/10%10]&0x7f;
smg[7]=Seg_Table[fram_freq%10];
}
if(mode_set==1)//湿度参数
{
smg[0]=0x8c;
smg[1]=Seg_Table[2];
smg[2]=0xff;
smg[3]=0xff;
smg[4]=0xff;
smg[5]=0xff;
smg[6]=Seg_Table[fram_west/10];
smg[7]=Seg_Table[fram_west%10];
}
if(mode_set==2)//距离参数
{
smg[0]=0x8c;
smg[1]=Seg_Table[3];
smg[2]=0xff;
smg[3]=0xff;
smg[4]=0xff;
smg[5]=0xff;
smg[6]=Seg_Table[fram_dist/10]&0x7f;
smg[7]=Seg_Table[fram_dist%10];
}
}
}
void vSmg_Show()
{
static unsigned char i;
vDevice_Process(0xc0,0);
vDevice_Process(0xe0,smg[i]);
vDevice_Process(0xc0,0x01<<i);
i = (i+1)%8;
}
//------------独立按键
unsigned char Trg,Cont;
void Three_line()
{
unsigned char ReadData=P3^0xff;
Trg = ReadData&(ReadData^Cont);
Cont = ReadData;
}
unsigned char cnt_key;
unsigned int cnt_1s;
void vKeys_Process()
{
if(cnt_key>=10)
{
cnt_key=0;
Three_line();
if(Trg == 0x08) //S4
{
mode1 = (mode1+1)%4;
if(mode1==0)led_ctrl.Hex=0xff;
if(mode1==3)
{
mode_set=0;
led_ctrl.Hex=0xff;
}
}
if(Trg == 0x04) //S5
{
if(mode1==3)
{
mode_set = (mode_set+1)%3;
}
}
if(Trg == 0x02) //S6
{
if(mode1==3)//参数界面下
{
switch(mode_set)
{
case 0:
fram_freq += 5;
if(fram_freq>120)fram_freq=10;
break;
case 1:
fram_west += 10;
if(fram_west>60)fram_west=10;
break;
case 2:
fram_dist += 1;
if(fram_dist>12)fram_dist=1;
break;
}
}
else if(mode1==2)//测距界面下
{
mode_dist = (mode_dist+1)%2;
}
}
if(Cont==0x01)//长按S7计时
{
cnt_1s++; //10ms加1 100就是1s
}
if(Cont == 0x00 &&Trg == 0x00)
{
if(cnt_1s>=100)//长按S7 清零继电器开关次数
{
cnt_1s=0;
}
else if(cnt_1s!=0)//短按S7
{
cnt_1s=0;
if(mode1==3)//参数界面下
{
switch(mode_set)
{
case 0:
fram_freq -= 5;
if(fram_freq<10)fram_freq=120;
break;
case 1:
fram_west -= 10;
if(fram_west<10)fram_west=60;
break;
case 2:
fram_dist -= 1;
if(fram_dist<1)fram_dist=12;
break;
}
}
else if(mode1==0)//测距界面下
{
mode_freq = (mode_freq+1)%2;
}
}
}
}
}
//----------LED 控制
unsigned int cnt_100msled;
void vLED_Process()
{
switch(mode1)
{
case 0:
led_ctrl.B.b1=0;//频率界面
led_ctrl.B.b2=1;
led_ctrl.B.b2=1;
break;
case 1:
led_ctrl.B.b1=1;
led_ctrl.B.b2=0;//湿度界面
led_ctrl.B.b3=1;
break;
case 2:
led_ctrl.B.b1=1;
led_ctrl.B.b2=1;
led_ctrl.B.b3=0;//距离界面
break;
}
vDevice_Process(0x80,led_ctrl.Hex);
}
//----------系统初始化
void vSystem_init()
{
led_ctrl.Hex=0xff;
vDevice_Process(0x80,0xff);
vDevice_Process(0xa0,0x00);
}
void main()
{
vSystem_init();
Timer2Init();
Timer0Init();
Timer1Init();
while(1)
{
vSmg_Process();
vGet_freq();
if(mode1==1)vGet_west();
vGet_dist();
vKeys_Process();
vDAC_Process();
}
}
unsigned char cnt_10; //100us十次就是1ms
void Timer2_service() interrupt 12
{
cnt_10++;
pwm++;
vPWM_out();
cnt_100msled++;
if(cnt_10>=10)
{
cnt_10=0;
cnt_freq++;cnt_rb2++;cnt_dist++;cnt_key++;
vSmg_Show();
}
vLED_Process();
if(cnt_100msled>=1000)
{
cnt_100msled=0;
if(mode1==3)
{
if(mode_set==0)//频率参数
{
led_ctrl.B.b1 = ~led_ctrl.B.b1;
led_ctrl.B.b2=1;
led_ctrl.B.b3=1;
}
if(mode_set==1)//频率参数
{
led_ctrl.B.b1=1;
led_ctrl.B.b2 = ~led_ctrl.B.b2;
led_ctrl.B.b3=1;
}
if(mode_set==2)//频率参数
{
led_ctrl.B.b1=1;
led_ctrl.B.b2=1;
led_ctrl.B.b3 = ~led_ctrl.B.b3;
}
}
}
if(state_RELAY==0)//继电器操作
{
if(dist>fram_dist*10)
{
state_RELAY=1;
vWrite_24c02(0x00,state_RELAY);
cnt_RELAY++;
vDevice_Process(0xa0,0x10); //闭合继电器
}
}
else if(state_RELAY==1)
{
if(dist<fram_dist*10)
{
state_RELAY=0;
vDevice_Process(0xa0,0x00);//断开继电器
}
}
}
iic.c
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <reg52.h>
#include <intrins.h>
#define DELAY_TIME 5
sbit sda=P2^1;
sbit scl=P2^0;
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
//测量RB2电压
unsigned char Read_rb2()
{
unsigned int dat;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
dat = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return dat*100/255; //0-100 注意这里先乘100所以要用int类型的dat
}
//输出电压dac
void Out_DAC(unsigned char dat)
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x40);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
//24c02写
void vWrite_24c02(unsigned char addr,unsigned char dat)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
Delay5ms();
}
iic.h
#ifndef __IIC_H__
#define __IIC_H__
unsigned char Read_rb2(); //0~100
void Out_DAC(unsigned char dat);
void vWrite_24c02(unsigned char addr,unsigned char dat);
#endif