0.比赛真题
1. 编程心得
- DAC输出需要放到while循环里,一直持续的输出才能检测到稳定电压
- 涉及锁存器5的部分:relay、buzz、motor……等不要放到while循环里,会造成蜂鸣器暴鸣。而是应该写一个带形参的函数,直接进行调用
- led的刷新:放在定时计数器里面,每2ms刷新一次比较恰当
- 涉及超声波的变量,无脑采用unsigned int
2.代码效果
波形输出需要有20%占空比和80%占空比两种,实测波形分别如下:
询问了学院博士,回答说高电平转低电平时,产生的向下的尖刺可能时由于motor端口,是用来驱动电机的,电路中自带一个电感,因此波形有向下的尖刺
3.单个模块代码
继电器和motor端口
超声波初始化函数
波形输出控制
4.完整参考代码
basecode.h
#ifndef __BASECODE_H__
#define __BASECODE_H__
unsigned char code duanma[20] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xc0,0x86,0x8e,0x89,0x8c,0x89,0x8c};
unsigned char code duanma_dot[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
void select_HC573 ( unsigned char channal );
void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG );
void state_SMG_all ( unsigned char value_SMG_all );
void init_sys ();
unsigned char pcf8591_rb2 ();
void pcf8591_dac ( unsigned char dac_value );
void at24c02_write ( unsigned char addr_value , unsigned char value );
unsigned char at24c02_read ( unsigned char addr_value );
#endif
basecode.c
#include <REGX51.H>
#include "iic.h"
void Delay() //@12.000MHz
{
unsigned char i, j;
i = 24;
j = 85;
do
{
while (--j);
} while (--i);
}
//锁存器通道选择函数
void select_HC573 ( unsigned char channal )
{
switch ( channal )
{
case 4:
P2 = ( P2 & 0x1f ) | 0x80;
break;
case 5:
P2 = ( P2 & 0x1f ) | 0xa0;
break;
case 6:
P2 = ( P2 & 0x1f ) | 0xc0;
break;
case 7:
P2 = ( P2 & 0x1f ) | 0xe0;
break;
case 0:
P2 = ( P2 & 0x1f );
break;
}
}
//单位数码管显示函数
void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{
P0 = 0x01 << pos_SMG;
select_HC573( 6 );
select_HC573 ( 0 );
P0 = value_SMG;
select_HC573( 7 );
select_HC573 ( 0 );
}
//全位数码管静态显示
void state_SMG_all ( unsigned char value_SMG_all )
{
P0 = 0xff;
select_HC573( 6 );
select_HC573 ( 0 );
P0 = value_SMG_all;
select_HC573( 7 );
select_HC573 ( 0 );
}
//初始化系统,关闭继电器和蜂鸣器
void init_sys ()
{
P0 = 0xff;
select_HC573 ( 4 );
select_HC573 ( 0 );
P0 = 0x00;
select_HC573 ( 5 );
select_HC573 ( 0 );
}
unsigned char pcf8591_rb2 ()
{
unsigned char rb2_value = 0;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x03);
I2CWaitAck();
I2CStop();
Delay();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
rb2_value = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return rb2_value;
}
void pcf8591_dac ( unsigned char dac_value )
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43);
I2CWaitAck();
I2CSendByte(dac_value);
I2CWaitAck();
I2CStop();
}
void at24c02_write ( unsigned char addr_value , unsigned char value )
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr_value);
I2CWaitAck();
I2CSendByte(value);
I2CWaitAck();
I2CStop();
}
/**
//用于测试eeprom是否成功写入
unsigned char at24c02_read ( unsigned char addr_value )
{
unsigned char tmp;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr_value);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
tmp = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return tmp;
}
**/
main.c
#include <intrins.h>
#include <REGX51.H>
#include "basecode.h"
sfr CMOD = 0xD9; //0xxx,x000 PCA 工作模式寄存器
sfr CL = 0xE9; //0000,0000 PCA计数器低字节
sfr CH = 0xF9; //0000,0000 PCA计数器高字节
sfr CCON = 0xD8; //00xx,xx00 PCA控制寄存器
sfr AUXR = 0x8e;
sbit TX = P1^0;
sbit RX = P1^1;
sbit s7 = P3^0;
sbit s6 = P3^1;
sbit s5 = P3^2;
sbit s4 = P3^3;
sbit CF = CCON^7;
sbit CR = CCON^6;
unsigned char SMG_mode = 1;
unsigned char flash_count = 0;
unsigned int dis_fre = 0;
unsigned int dis_k_fre = 0;
unsigned char dis_humidity = 0;
unsigned int dis_distance = 0;
unsigned char param_k_fre = 90;
unsigned char param_m_distance = 60;
unsigned char param_humidity = 40;
void flash_SMG ();
void state_led ( unsigned char value_led )
{
select_HC573 ( 0 );
P0 = value_led;
select_HC573 ( 4 );
select_HC573 ( 0 );
}
unsigned char hc573_5_value = 0x00;
unsigned char value_led = 0xff;
void relay_work( unsigned char relay_flag )
{
if ( relay_flag == 1 )
hc573_5_value |= 0x10;
else
hc573_5_value &= ~0x10;
P0 = hc573_5_value;
select_HC573 ( 5 );
select_HC573 ( 0 );
}
void motor_work( unsigned char motor_flag )
{
if ( motor_flag == 1 )
hc573_5_value |= 0x20;
else
hc573_5_value &= ~0x20;
P0 = hc573_5_value;
select_HC573 ( 5 );
select_HC573 ( 0 );
}
void Delay14us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 36;
while (--i);
}
void init_pca ()
{
CMOD = 0x00;
CCON = 0x00;
}
void send_sonic ()
{
unsigned char i;
TR1 = TR0 = 0;
for ( i=0 ; i<8 ; i++ )
{
TX = 1;
Delay14us();
TX = 0;
Delay14us();
}
TR1 = TR0 = 1;
}
bit flag_sonic = 0;
void flash_sonic ()
{
if ( flag_sonic == 1 )
{
unsigned int time;
CL = CH = 0;
CF = 0;
send_sonic ();
CR = 1;
while ( RX == 1 && CF == 0 );
CR = 0;
if ( RX == 1 )
{
dis_distance = 999;
CF = 0;
}
else
{
time = CH;
time = (time<<8) | CL;
dis_distance = (unsigned int)(time*0.0172);
}
flag_sonic = 0;
dis_distance = dis_distance;
}
}
unsigned char rb2_value;
bit flag_rb2 = 0;
void flash_rb2 ()
{
if ( flag_rb2 == 1 )
{
rb2_value = pcf8591_rb2 ();
flag_rb2 = 0;
}
}
void init_timer1(void) //50微秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xCE; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
void init_timer0 (void)
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x06; //设置定时器模式
TL0 = 0xff; //设置定时初始值
TH0 = 0xff; //设置定时重载值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
unsigned int count_fre = 0;
void timer0_service () interrupt 1
{
count_fre ++ ;
}
unsigned char count_50us = 0;
unsigned char count_10ms = 0;
unsigned char count_5ms = 0;
unsigned char count_relay = 0;
//unsigned char count_relay_test = 0x00;//用于数码管,测试eeprom的数据是否写入成功
unsigned char count_motor = 0;
unsigned int count_relay_50us = 0;
bit led_100ms = 0;
bit flag_dac = 0;
bit clear_relay = 0;
bit clear_relay_1s = 0;
bit count_motor_flag = 0;
bit count_relay_flag = 0;
void timer1_service () interrupt 3
{
if ( ++count_50us == 200 )
{
count_50us = 0;
if ( ++count_10ms == 100 )
{
count_10ms = 0;
dis_fre = count_fre;
count_fre = 0;
}
}
if ( count_50us % 100 == 0 )
{
count_5ms++;
if ( count_5ms == 200 )
{
count_5ms = 0;
flag_sonic = 1;
}
if ( count_5ms % 20 == 0 )
led_100ms = ~led_100ms;
if ( count_5ms % 100 == 0 ) //外设刷新时间控制
{
flag_rb2 = 1;
flag_dac = 1;
}
}
if ( count_motor_flag == 1 )
{
if ( ++count_motor < 160 )
{
motor_work(1);
}
else
{
motor_work(0);
}
}
else if ( count_motor_flag == 0 )
{
if ( ++count_motor < 40 )
{
motor_work(1);
}
else
{
motor_work(0);
}
}
if ( count_motor >= 20 )
{
count_motor = 0;
}
if ( clear_relay == 1 )
{
if ( ++count_relay_50us > 2000 )
{
clear_relay_1s = 1;
}
}
if ( count_50us % 40 == 0 )
{
if ( SMG_mode == 3 )
{
if ( ++flash_count > 2 )
{
flash_count = 0;
}
}
else if ( SMG_mode == 4 || SMG_mode == 5 || SMG_mode == 7 || SMG_mode == 8 )
{
if ( ++flash_count > 3 )
{
flash_count = 0;
}
}
else if ( SMG_mode == 6 )
{
if ( ++flash_count > 4 )
{
flash_count = 0;
}
}
else if ( SMG_mode == 1 || SMG_mode == 2 )
{
if ( ++flash_count == 7 )
{
flash_count = 0;
}
}
flash_SMG ();
state_led ( value_led );
}
}
void value_running ()
{
unsigned char temp_dac = 0;
dis_k_fre = dis_fre/100;
if ( rb2_value > 254 )
{
dis_humidity =99;
}
else
{
dis_humidity = (int)(rb2_value/2.55);
}
if ( dis_humidity > 80 )
{
temp_dac = 255;
}
else if ( dis_humidity > param_humidity )
{
temp_dac = (int)(dis_humidity*(4.0/80-param_humidity));
value_led &= 0xef;
}
else
{
temp_dac = 52;
value_led |= 0x10;
}
pcf8591_dac ( temp_dac );
flag_dac = 0;
if ( clear_relay == 1 )
{
if ( clear_relay_1s == 1 )
{
count_relay = 0;
at24c02_write ( 0x00 , count_relay );
}
}
else
{
clear_relay_1s = 0;
count_relay_50us = 0;
}
if ( dis_distance > param_m_distance )
{
relay_work( 1 );
value_led &= 0xdf;
if ( count_relay_flag == 1 )
{
count_relay++;
count_relay_flag = 0;
at24c02_write ( 0x00 , count_relay );
}
}
else
{
relay_work( 0 );
value_led |= 0x20;
count_relay_flag = 1;
}
if ( dis_k_fre > param_k_fre )
{
count_motor_flag = 1;
value_led &= 0xf7;
}
else
{
count_motor_flag = 0;
value_led |= 0x08;
}
//频率界面12 湿度界面3 测距界面45 参数界面678
if ( SMG_mode == 1 || SMG_mode == 2 )
{
value_led |= 0x06;
if ( led_100ms == 1 )
value_led &= 0xfe;
else
value_led |= 0x01;
}
else if ( SMG_mode == 3 )
{
value_led |= 0x05;
if ( led_100ms == 1 )
value_led &= 0xfd;
else
value_led |= 0x02;
}
else if (SMG_mode == 4 || SMG_mode == 5 )
{
value_led |= 0x03;
if ( led_100ms == 1 )
value_led &= 0xfb;
else
value_led |= 0x04;
}
}
void flash_SMG ()
{
state_SMG_all ( 0xff );
if ( SMG_mode == 1 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[15] );break;
case 1:
if ( dis_fre > 99999 )
state_SMG ( 2 , duanma[dis_k_fre/100000] );
else
state_SMG ( 2 , 0xff );
break;
case 2:
if ( dis_fre > 9999 )
state_SMG ( 3 , duanma[dis_fre/10000%10] );
else
state_SMG ( 3 , 0xff );
break;
case 3:
if ( dis_fre > 999 )
state_SMG ( 4 , duanma[dis_fre/1000%10] );
else
state_SMG ( 4 , 0xff );
break;
case 4:
if ( dis_fre > 99 )
state_SMG ( 5 , duanma[dis_fre/100%10] );
else
state_SMG ( 5 , 0xff );
break;
case 5:
if ( dis_fre > 9 )
state_SMG ( 6 , duanma[dis_fre/10%10] );
else
state_SMG ( 6 , 0xff );
break;
case 6:
state_SMG ( 7 , duanma[dis_fre%10] );
}
}
else if ( SMG_mode == 2 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[15] );break;
case 1:
if ( dis_k_fre > 9999 )
state_SMG ( 2 , duanma[dis_k_fre/100000] );
else
state_SMG ( 2 , 0xff );
break;
case 2:
if ( dis_k_fre > 9999 )
state_SMG ( 3 , duanma[dis_k_fre/10000%10] );
else
state_SMG ( 3 , 0xff );
break;
case 3:
if ( dis_k_fre > 999 )
state_SMG ( 4 , duanma[dis_k_fre/1000%10] );
else
state_SMG ( 4 , 0xff );
break;
case 4:
if ( dis_k_fre > 99 )
state_SMG ( 5 , duanma[dis_k_fre/100%10] );
else
state_SMG ( 5 , 0xff );
break;
case 5:
if ( dis_k_fre > 9 )
state_SMG ( 6 , duanma_dot[dis_k_fre/10%10] );
else if ( dis_k_fre < 10 )
state_SMG ( 6 , duanma_dot[0] );
else
state_SMG ( 6 , 0xff );
break;
case 6:
state_SMG ( 7 , duanma[dis_k_fre%10] );
}
}
else if ( SMG_mode == 3 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[16] );break;
case 1:state_SMG ( 6 , duanma[dis_humidity/10] );break;
case 2:state_SMG ( 7 , duanma[dis_humidity%10] );break;
}
}
/** else if ( SMG_mode == 3 ) //用于测试eeprom的数据是否写入成功
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[14] );break;
case 1:state_SMG ( 6 , duanma[count_relay_test/16] );state_SMG ( 3 , duanma[count_relay/10] );break;
case 2:state_SMG ( 7 , duanma[count_relay_test%16] );state_SMG ( 4 , duanma[count_relay%10] );break;
}
}**/
else if ( SMG_mode == 4 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[10] );break;
case 1:
if ( dis_distance > 99 )
state_SMG ( 5 , duanma[dis_distance/100] );
else
state_SMG ( 5 , 0xff );
break;
case 2:
if ( dis_distance > 9 )
state_SMG ( 6 , duanma[dis_distance/10%10] );
else
state_SMG ( 6 , 0xff );
break;
case 3:state_SMG ( 7 , duanma[dis_distance%10] );break;
}
}
else if ( SMG_mode == 5 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[10] );break;
case 1:
if ( dis_distance < 99 )
state_SMG ( 5 , duanma_dot[0] );
else
state_SMG ( 5 , duanma_dot[dis_distance/100] );
break;
case 2:state_SMG ( 6 , duanma[dis_distance/10%10] );break;
case 3:state_SMG ( 7 , duanma[dis_distance%10] );break;
}
}
else if ( SMG_mode == 6 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[17] );break;
case 1:state_SMG ( 1 , duanma[1] );break;
case 2:
if ( param_k_fre > 99 )
state_SMG ( 5 , duanma_dot[param_k_fre/100] );
else
state_SMG ( 5 , 0xff );
break;
case 3:
if ( param_k_fre > 9 && param_k_fre < 99 )
state_SMG ( 6 , duanma_dot[param_k_fre/10%10] );
else if ( param_k_fre > 99 )
state_SMG ( 6 , duanma[param_k_fre/10%10] );
else
state_SMG ( 6 , 0xff );
break;
case 4:state_SMG ( 7 , duanma[param_k_fre%10] );break;
}
}
else if ( SMG_mode == 7 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[17] );break;
case 1:state_SMG ( 1 , duanma[2] );break;
case 2:state_SMG ( 6 , duanma[param_humidity/10] );break;
case 3:state_SMG ( 7 , duanma[0] );break;
}
}
else if ( SMG_mode == 8 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[17] );break;
case 1:state_SMG ( 1 , duanma[3] );break;
case 2:state_SMG ( 6 , duanma_dot[param_m_distance/10] );break;
case 3:state_SMG ( 7 , duanma[param_m_distance%10] );break;
}
}
}
void Delay2ms() //@12.000MHz
{
unsigned char i, j;
i = 24;
j = 85;
do
{
while (--j);
} while (--i);
}
void key_scan ()
{
if ( s7 == 0 )
{
Delay2ms();
if ( s7 == 0 )
{
//频率界面12 湿度界面3 测距界面45 参数界面678
if ( SMG_mode == 6 )
{
param_k_fre -= 5;
if ( param_k_fre == 5 )
param_k_fre = 120;
}
else if ( SMG_mode == 7 )
{
param_humidity -= 10;
if ( param_humidity == 0 )
param_humidity = 60;
}
else if ( SMG_mode == 8 )
{
param_m_distance -= 1;
if ( param_m_distance == 0 )
param_m_distance = 12;
}
else if ( SMG_mode == 1 )
{
SMG_mode = 2;
}
else if ( SMG_mode == 2 )
{
SMG_mode = 1;
}
else if ( SMG_mode == 3 )
{
clear_relay = 1;
}
while ( s7 == 0 );
clear_relay = 0;
}
}
else if ( s6 == 0 )
{
Delay2ms();
if ( s6 == 0 )
{
//频率界面12 湿度界面3 测距界面45 参数界面678
if ( SMG_mode == 6 )
{
param_k_fre += 5;
if ( param_k_fre == 125 )
param_k_fre = 10;
}
else if ( SMG_mode == 7 )
{
param_humidity += 10;
if ( param_humidity == 70 )
param_humidity = 10;
}
else if ( SMG_mode == 8 )
{
param_m_distance += 1;
if ( param_m_distance == 13 )
param_m_distance = 1;
}
else if ( SMG_mode == 4 )
{
SMG_mode = 5;
}
else if ( SMG_mode == 5 )
{
SMG_mode = 4;
}
while ( s6 == 0 );
}
}
else if ( s5 == 0 )
{
Delay2ms();
if ( s5 == 0 )
{
switch ( SMG_mode )
{
case 6:SMG_mode = 7;break;
case 7:SMG_mode = 8;break;
case 8:SMG_mode = 6;break;
}
while ( s5 == 0 );
}
}
else if ( s4 == 0 )
{
Delay2ms();
if ( s4 == 0 )
{
switch ( SMG_mode )
{
case 1:case 2:
SMG_mode = 3;break;
case 3:
SMG_mode = 4;break;
case 4:case 5:
SMG_mode = 6;break;
case 6:case 7:case 8:
SMG_mode = 1;break;
}
while ( s4 == 0 );
}
}
}
void main ()
{
init_sys ();
init_timer0 ();
init_timer1 ();
init_pca ();
// at24c02_write ( 0x00 , count_relay );
// Delay2ms ();
// count_relay_test = at24c02_read( 0x00 ); //用于测试eeprom是否写入成功
while ( 1 )
{
key_scan ();
value_running ();
flash_rb2 ();
flash_sonic ();
}
}