0.编程心得
本题中,要求测距能达到250cm,因此pca必须配置为0x01,但直接用会死机,因此需要使用CH作为判断量。
【iic的at24c02记录】:读设备地址:0xA1 写设备地址:0xA0
非应答信号:sda先1,后还是1。本届直接实参传1就是非应答
02表示2k大小
时序操作可完全参考手册
【onewire的ds18b20】:MSB | LSB 的高5位全0,则读取温度为正数。全1则读取温度为负数 精度为0.0625
时序要自己背:初始化、写入0xcc、写入0x44、延时800ms、初始化、写入0xcc、写入0xbe、读取数据
LSB = Read_DS18B20(); 先读出来的是低八位
MSB = Read_DS18B20();
temperature = MSB;
temperature = ( temperature << 8 ) | LSB;
temperature = (temperature >> 4)*10 + (LSB & 0x0f)*0.625;
刷新时间:2s刷新一次!!!!
数据如果闪烁,就在底层代码的读取函数中,在DQ电平变高后加一个5us
【led的刷新】:刷新可以和数码管一起,40个50us刷新一次,2ms
涉及锁存器5的所有操作,都不要放while循环里。而且设置形参,直接调用
【iic的pcf8591记录】:读设备地址:0x91 写设备地址:0x90
控制字:0 D/A-flag x x 0 x A/Dchannal
channal:00 外部模拟信号控制端
01 光敏电阻rd1 0x01
10 差分放大电路信号
11 滑动变阻器rb2 0x03
void dacrunning ( unsigned char value_dac ) //DAC输出,不能设置刷新位,要一直输出
{
I2CStart();
I2CSendByte( 0x90 );
I2CWaitAck();
I2CSendByte( 0x43 );
I2CWaitAck();
I2CSendByte( value_dac );
I2CWaitAck();
I2CStop();
}
输出DAC:0x43
1.比赛真题
2.特殊模块
字节反序程序
超声波程序
双按键程序
双按键下的delay函数要长一些,不然容易误判,因此人不可能做到100%同时按下
3.参考代码
main.c
cpp
#include <REGX52.H>
#include <intrins.h>
#include "iic.h"
#include "onewire.h"
sfr AUXR = 0x8e;
sfr P4 = 0xc0;
sfr CCON = 0xD8; //00xx,xx00 PCA控制寄存器
sbit CF = CCON^7;
sbit CR = CCON^6;
sfr CMOD = 0xD9; //0xxx,x000 PCA 工作模式寄存器
sfr CL = 0xE9; //0000,0000 PCA计数器低字节
sfr CH = 0xF9; //0000,0000 PCA计数器高字节
sbit TX = P1^0;
sbit RX = P1^1;
sbit C1 = P4^4;
sbit C2 = P4^2;
sbit R3 = P3^2;
sbit R4 = P3^3;
unsigned char param_mode = 1;
unsigned char SMG_mode = 1;
unsigned char param_distance = 40;
unsigned char param_temperature = 30;
unsigned char param_dac = 10;
unsigned int param_V = 340;
unsigned char save_distance = 0;
unsigned char value_led = 0xff;
float value_sonic = 0.0;
int param_calibration = 0;
bit flag_reset = 0;
bit flag_dac = 0;
bit flag_m_distance = 0;
bit flag_save_distance = 0;
unsigned char code duanma[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xc0,0x86,0x8e,0xbf,0x8c};
unsigned char code duanma_dot[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
void scan_key ();
void value_work ();
unsigned char reverse_bit ( unsigned char dat )
{
dat = (dat & 0xF0) >> 4 | (dat & 0x0F) << 4;
dat = (dat & 0xCC) >> 2 | (dat & 0x33) << 2;
dat = (dat & 0xAA) >> 1 | (dat & 0x55) << 1;
return dat;
}
void select_HC573 ( unsigned char channal , unsigned char dat )
{
P2 = (P2&0x1f)|0x00;
P0 = dat;
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;
}
P2 = (P2&0x1f)|0x00;
}
void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{
select_HC573 ( 6 , 0x01<<pos_SMG );
select_HC573 ( 7 , value_SMG );
}
void state_SMG_all ( unsigned char value_SMG )
{
select_HC573 ( 6 , 0xff );
select_HC573 ( 7 , value_SMG );
}
void init_pca ()
{
CMOD = 0x01;
CCON = 0x00;
}
void Delay13us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 38;
while (--i);
}
bit flash_sonic = 0;
unsigned int dis_distance = 0;
void send_sonic ()
{
unsigned char i;
for ( i=0 ; i<8 ; i++ )
{
TX = 1;
Delay13us();
TX = 0;
Delay13us();
}
}
void recive_sonic ()
{
if ( flash_sonic == 1 )
{
unsigned int tmp = 0;
CL = CH = CF = 0;
EA = 0;
send_sonic ();
EA = 1;
CR = 1;
while ( RX==1 && CH < 0x40 );
CR = 0;
if ( CH > 0x40 )
{
CF = 0;
tmp = 999;
}
else
{
tmp = CH;
tmp = (tmp<<8)|CL;
tmp = (unsigned int)(tmp*value_sonic+param_calibration);
}
dis_distance = tmp;
flash_sonic = 0;
if ( flag_save_distance == 1 )
save_distance = tmp;
}
}
void Delay800ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 37;
j = 123;
k = 92;
do
{
do
{
value_work();
scan_key ();
while (--k);
} while (--j);
} while (--i);
}
bit flash_ds18b20 = 0;
unsigned int dis_temperature = 0;
void recive_ds18b20 ( )
{
if ( flash_ds18b20 == 1 )
{
unsigned int tmp = 0;
unsigned char MSB,LSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay800ms();
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
tmp = MSB;
tmp = (tmp<<8)|LSB;
// tmp = (tmp>>4)*10+(LSB&0x0f)*0.625;
tmp = (unsigned int)tmp*0.625;
dis_temperature = tmp;
flash_ds18b20 = 0;
}
}
unsigned char dac_value = 0;
void dac_work ( unsigned char dac_value )
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43);
I2CWaitAck();
I2CSendByte(dac_value);
I2CWaitAck();
I2CStop();
}
unsigned char flash_count = 0;
void flash_SMG ()
{
state_SMG_all ( 0xff );
if ( SMG_mode == 1 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[dis_temperature/100] );break;
case 1:state_SMG ( 1 , duanma_dot[dis_temperature/10%10] );break;
case 2:state_SMG ( 2 , duanma[dis_temperature%10] );break;
case 3:state_SMG ( 3 , duanma[16] );break;
case 4:
if ( dis_distance > 999 )
state_SMG ( 4 , duanma[dis_distance/1000] );
else
state_SMG ( 4 , 0xff );
break;
case 5:
if ( dis_distance > 99 && flag_m_distance == 0 )
state_SMG ( 5 , duanma[dis_distance/100%10] );
else if ( flag_m_distance == 1 )
state_SMG ( 5 , duanma_dot[dis_distance/100%10] );
else
state_SMG ( 5 , 0xff );
break;
case 6:
if ( dis_distance > 9 && flag_m_distance == 0 )
state_SMG ( 6 , duanma[dis_distance/10%10] );
else if ( flag_m_distance == 1 )
state_SMG ( 6 , duanma[dis_distance/10%10] );
else
state_SMG ( 6 , 0xff );
break;
case 7:state_SMG ( 7 , duanma[dis_distance%10] );break;
}
}
else if ( SMG_mode == 2 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[17] );break;
case 1:state_SMG ( 1 , duanma[param_mode] );break;
case 2:
if ( param_mode == 1 )
state_SMG ( 6 , duanma[param_distance/10] );
else
state_SMG ( 6 , duanma[param_temperature/10] );
break;
case 3:
if ( param_mode == 1 )
state_SMG ( 7 , duanma[param_distance%10] );
else
state_SMG ( 7 , duanma[param_temperature%10] );
break;
}
}
else if ( SMG_mode == 3 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[15] );break;
case 1:state_SMG ( 1 , duanma[1] );break;
case 2:
if ( param_calibration > 99 )
state_SMG ( 5 , duanma[param_calibration/100] );
else if ( param_calibration < -9 )
state_SMG ( 5 , duanma[16] );
else
state_SMG ( 5 , 0xff );
break;
case 3:
if ( param_calibration > 9 )
state_SMG ( 6 , duanma[param_calibration/10%10] );
else if ( param_calibration < 0 && param_calibration > -9 )
state_SMG ( 6 , duanma[16] );
else if ( param_calibration < 9 && param_calibration != 0 )
state_SMG ( 6 , duanma[(-1)*param_calibration/10%10] );
else
state_SMG ( 6 , 0xff );
break;
case 4:
if ( param_calibration > 0)
state_SMG ( 7 , duanma[param_calibration%10] );
else
state_SMG ( 7 , duanma[(-1*param_calibration)%10] );
break;
}
}
else if ( SMG_mode == 4 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[15] );break;
case 1:state_SMG ( 1 , duanma[2] );break;
case 2:
if ( param_V > 999 )
state_SMG ( 4 , duanma[param_V/1000] );
else
state_SMG ( 4 , 0xff );
break;
case 3:
if ( param_V > 99 )
state_SMG ( 5 , duanma[param_V/100%10] );
else
state_SMG ( 5 , 0xff );
break;
case 4:
if ( param_V > 9 )
state_SMG ( 6 , duanma[param_V/10%10] );
else
state_SMG ( 6 , 0xff );
break;
case 5:state_SMG ( 7 , duanma[param_V%10] );break;
}
}
else if ( SMG_mode == 5 )
{
switch ( flash_count )
{
case 0:state_SMG ( 0 , duanma[15] );break;
case 1:state_SMG ( 1 , duanma[3] );break;
case 2:state_SMG ( 6 , duanma_dot[param_dac/10] );break;
case 3:state_SMG ( 7 , duanma[param_dac%10] );break;
}
}
}
void reset_work ()
{
SMG_mode = 1;
param_distance = 40;
param_temperature = 30;
param_calibration = 0;
param_V = 340;
param_dac = 10;
}
void init_timer0(void) //50微秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x02; //设置定时器模式
TL0 = 0xCE; //设置定时初始值
TH0 = 0xCE; //设置定时重载值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
unsigned char count_50us = 0;
unsigned char count_10ms = 0;
bit flag_100ms = 0;
unsigned char count_save_10ms = 0;
unsigned char count_save_1s = 0;
unsigned char count_reset = 0;
void timer0_service () interrupt 1
{
if ( ++count_50us == 200 )
{
count_50us = 0;
if ( ++count_10ms == 200 )
count_10ms = 0;
if ( flag_save_distance == 1 )
{
if ( ++count_save_10ms == 100 )
{
count_save_10ms = 0;
if ( ++count_save_1s == 6 )
flag_save_distance = 0;
}
}
else
{
count_save_10ms = 0;
count_save_1s = 0;
}
if ( flag_reset == 1 )
{
if ( ++count_reset == 200 )
reset_work();
}
else
count_reset = 0;
}
if ( count_50us % 40 == 0 ) //刷新数码管和led
{
if ( SMG_mode == 1 )
{
if ( ++flash_count == 8 )
flash_count= 0;
}
else if ( SMG_mode == 4 )
{
if ( ++flash_count > 5 )
flash_count= 0;
}
else if ( SMG_mode == 2 || SMG_mode == 5 )
{
if ( ++flash_count > 3 )
flash_count= 0;
}
else if ( SMG_mode == 3 )
{
if ( ++flash_count > 4 )
flash_count= 0;
}
flash_SMG ();
select_HC573 ( 4 , value_led );
}
if ( count_10ms % 50 == 0 )
{
flash_sonic = 1;
}
if ( count_10ms % 100 == 0 )//让温度和超声波不同时刷新,避免数据问题
{
flash_ds18b20 = 1;
}
if ( SMG_mode == 1 )
{
if ( dis_distance > 255 )
value_led = 0x00;
else
value_led = reverse_bit( ~(dis_distance/8) );
}
else if ( SMG_mode == 2 )
value_led = 0x7f;
else if ( SMG_mode > 2 )
{
if ( count_10ms % 10 == 0 )
value_led = 0xfe;
else
value_led = 0xff;
}
}
void value_work ()
{
if ( flag_dac == 1 && save_distance != 0 )
{
if ( save_distance > 90 )
dac_value = 255;
else if ( save_distance > 10 )
dac_value = (3.2-0.05*param_dac)*save_distance;
else
dac_value = param_dac*5.1;
flag_dac = 0;
}
if ( dis_distance <= param_distance+5 && dis_distance >= param_distance-5 && dis_temperature <= param_temperature*10 )
select_HC573 ( 5 , 0x10 );
else
select_HC573 ( 5 , 0x00 );
}
void Delay2ms() //@12.000MHz
{
unsigned char i, j;
i = 24;
j = 85;
do
{
while (--j);
} while (--i);
}
void Delay30ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 2;
j = 95;
k = 43;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void scan_key ()
{
if ( flag_save_distance == 1 )
return;
C1 = 0;
C2 = R3 = R4 = 1;
if ( R3 == 0 )
{
Delay2ms();
if ( R3 == 0 ) //5
{
//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出
if ( SMG_mode == 1 )
{
if ( flag_m_distance == 0 )
flag_m_distance = 1;
else if ( flag_m_distance == 1 )
flag_m_distance = 0;
}
else if ( SMG_mode == 2 )
{
if ( param_mode == 1 )
param_mode = 2;
else if ( param_mode == 2 )
param_mode = 1;
}
else
{
switch ( SMG_mode )
{
case 3:SMG_mode = 4;break;
case 4:SMG_mode = 5;break;
case 5:SMG_mode = 3;break;
}
}
while ( R3 == 0 );
}
}
else if ( R4 == 0 )
{
Delay2ms();
if ( R4 == 0 ) //4
{
switch ( SMG_mode )
{
//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出
case 1:SMG_mode = 2;param_mode = 1;break;
case 2:SMG_mode = 3;break;
case 3:case 4:case 5:SMG_mode = 1;break;
}
while ( R4 == 0 );
}
}
C2 = 0;
C1 = R3 = R4 = 1;
if ( R3 == 0 || R4 == 0 )
{
Delay30ms();
if ( R3 == 0 && R4 == 0 )
{
flag_reset = 1;
while ( R3 == 0 && R4 == 0 )
{
flag_reset = 1;
}
flag_reset = 0;
}
else if ( R3 == 0 ) //9
{
//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出
if ( SMG_mode == 2 && param_mode == 1 )
param_distance -= 10;
else if ( SMG_mode == 2 && param_mode == 2 )
param_temperature -= 10;
else if ( SMG_mode == 3 )
param_calibration -= 5;
else if ( SMG_mode == 4 ){
param_V -= 10;value_sonic = (float)param_V/2/100;}
else if ( SMG_mode == 5 )
param_dac -=1;
else if ( SMG_mode == 1 )
flag_dac = 1;
if ( param_distance < 10 )
param_distance = 10;
else if ( param_temperature > 100 ) //越位了会变成255
param_temperature = 0;
else if ( param_calibration < -90 )
param_calibration = -90;
else if ( param_V < 10 )
param_V = 10;
else if ( param_dac < 1 )
param_dac = 1;
value_sonic = (float)(param_V)*0.00005;
while ( R3 == 0 );
}
else if ( R4 == 0 ) //8
{
//测距界面1 参数界面2 工厂模式3校准值4介质设置5dac输出
if ( SMG_mode == 2 && param_mode == 1 )
param_distance += 10;
else if ( SMG_mode == 2 && param_mode == 2 )
param_temperature += 10;
else if ( SMG_mode == 3 )
param_calibration += 5;
else if ( SMG_mode == 4 ){
param_V += 10;value_sonic = (float)param_V*0.00005;}
else if ( SMG_mode == 5 )
param_dac +=1;
else if ( SMG_mode == 1 )
flag_save_distance = 1;
if ( param_distance > 90 )
param_distance = 90;
else if ( param_temperature > 80 ) //越位了会变成255
param_temperature = 80;
else if ( param_calibration > 90 )
param_calibration = 90;
else if ( param_V > 9990 )
param_V = 9990;
else if ( param_dac > 20 )
param_dac = 20;
value_sonic = (float)(param_V)*0.00005;
while ( R4 == 0 );
}
}
}
void init_sys ()
{
select_HC573 ( 4 , 0xff );
select_HC573 ( 5 , 0x00 );
value_sonic = (float)(param_V)*0.00005;
}
void main ()
{
init_sys ();
init_timer0 ();
init_pca ();
while ( 1 )
{
scan_key ();
value_work();
recive_sonic ();
recive_ds18b20 ();
dac_work ( dac_value );
}
}