题目如下,按键扫描用的是中断扫描,自从学会了中断扫描的方法之后用了还想用,因为消抖很好。还有就是我总结了一些细节问题:主要太马虎了,写的时候会因为一个小错误浪费世间,所以每次写的时候把遇到的问题写下来,供自己回顾记忆,都很简单,看看笑笑就好:
//main写成了mian
//按键扫描的时候规定按键按下为0,
// case 0:h0=0;h1=1;break;
// case 1:h1=0;h0=1;break;
// 扫描那一行就把哪一行拉低,因为按下为零是我们判断条件 也试了设置为按下为高,case 0:h0=1;h1=0;break;
// 但是上电会执行一次按键number会变为1,不知道为啥,所以还是设置为按下为低,number是我验证按键函数是否正确而定义的一个变量,然后数码管显示出来,最后再删了
//读取温度的4个命令 0xcc 0x44 0xcc 0xbe
// 串口中断标志位要开 ES=1; RI要及时清零
// 每次添加完新的点c文件不要忘记添加进组里
// 定义一个数组char arry[13];
// 定义接收命令command类型为char 把中断服务函数放进main.c函数(主函数)才能执行切换页面操作,不知道为什么,放在usart.c里就不行,这个是第二次敲的时候遇到的问题,我嫌都放在一个点C文件里太长,找函数不好找,就分开了一个usart.c文件,但是led灯等函数没写,就把第一遍写的代码发上来了
// sendstring函数
// 按键发送数据只能发送一次的问题:发送字符串函数定义变量i定义成了static ,发送完一次数据没有清零,所以按键12只能发一次,改成局部变量即可多次发送
主函数代码如下
#include "stc15f2k60s2.h"
#include "iic.h"
#include "onewire.h"
#include "stdio.h"
unsigned char dscom=0;
unsigned char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xc1};
unsigned char dsbuff[8]={0};
unsigned char ad_value=0;
unsigned int ad_value_D=0;
unsigned int wendu_value;
bit ad_flag=0;
bit wendu_flag=0;
bit l1_flag=0;
bit l2_flag=0;
bit lock_flag=0;
bit jdq_flag=0;
bit beep_flag=0;
unsigned char led_num=0xff;
unsigned char jdq_num=0x00;
unsigned char keysta[2][4]={{1,1,1,1},{1,1,1,1}};
unsigned char keybackup[2][4]={{1,1,1,1},{1,1,1,1}};
unsigned char keybuff[2][4]={{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff}};
unsigned char code keycode[2][4]={{5,9,13,17},{4,8,12,16}};
sbit l0=P4^4;
sbit l1=P4^2;
sbit l2=P3^5;
sbit l3=P3^4;
sbit h2=P3^2;
sbit h3=P3^3;
unsigned char number=0;
char arry[10]="dasdasd";
unsigned char ym_mode=2;
unsigned int ad_t=0;
unsigned char l3_count=0;
void keyaction(unsigned char keydat);
void keysong(unsigned char keydat);
void yemian();
void select573(unsigned char channel)
{
P2&=0x1f;
P0=0xff;
switch(channel)
{
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;
}
}
void allinit()
{
select573(4);P0=0xff;
select573(5);P0=0x00;
select573(6);P0=0xff;
select573(7);P0=0xff;
}
void display()
{
select573(7);P0=0xff;
select573(6);P0=1<<dscom;
select573(7);
if(ym_mode==2&&dscom==6)
{
P0=tab[dsbuff[dscom]]&0x7f;
}
else if(ym_mode==1&&dscom==5)
{
P0=tab[dsbuff[dscom]]&0x7f;
}
else
P0=tab[dsbuff[dscom]];
P2&=0x1f;
if(++dscom>=8)
dscom=0;
}
void timer0init()
{
TMOD=TMOD&0xf0;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
TF0=0;
TR0=1;
ET0=1;
EA=1;
}
void UartInit(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR &= 0xFB; //定时器2时钟为Fosc/12,即12T
T2L = 0xE6; //设定定时初值
T2H = 0xFF; //设定定时初值
AUXR |= 0x10; //启动定时器2
ES=1;
}
//==================串口发送函数==============================================================================================
void sendbyte(unsigned char bdat)
{
SBUF=bdat;
while(TI==0);
TI=0;
}
void sendstring(char str[])
{
unsigned char i=0;
while(str[i]!='\0')
{
sendbyte(str[i]);
i++;
}
}
void usart()interrupt 4
{
char command;
if(RI==1)
{
RI=0;
command=SBUF;
if(command=='A')
{
ym_mode=2;
}
else if(command=='B')
{
ym_mode=1;
}
}
}
//==================按键函数==============================================================================================
void keyscan()
{
unsigned char i;
static unsigned char j=0;
keybuff[j][0]=keybuff[j][0]<<1|l0;
keybuff[j][1]=keybuff[j][1]<<1|l1;
keybuff[j][2]=keybuff[j][2]<<1|l2;
keybuff[j][3]=keybuff[j][3]<<1|l3;
for(i=0;i<4;i++)
{
if((keybuff[j][i]&0x0f)==0)
keysta[j][i]=0;
else if((keybuff[j][i]&0x0f)==0x0f)
keysta[j][i]=1;
}
j++;
if(j>=2)
j=0;
switch(j)
{
case 0:h2=0;h3=1;break;
case 1:h3=0;h2=1;break;
}
}
//==================按键处理
void keyhandle()
{
unsigned char i,j;
for(i=0;i<2;i++)
{
for(j=0;j<4;j++)
{
if(keybackup[i][j]!=keysta[i][j])
{
if(keysta[i][j]==0)
{
keyaction(keycode[i][j]);
}
else if(keysta[i][j]==1)
{
keysong(keycode[i][j]);
}
}
keybackup[i][j]=keysta[i][j];
}
}
}
void keyaction(unsigned char keydat)
{
float t;
if(keydat==4)//按键S4定义为“锁定”按键,按下S4按键,能够锁定当前界面“温度显示界面”或“电压显示界面”,串口切换界面指令失效。
{
lock_flag=1;
ES=0;
}
else if(keydat==5)//按键S5定义为“解锁”按键,在界面锁定时,按下S5按键,可取消界面锁定,串口指令恢复控制
{
lock_flag=0;
led_num|=0x04;
ES=1;
}
else if(keydat==12)//按键S12定义为“发送”按键,每次按下,串口将当前数码管显示的数据发送给PC端的串口调试工具。
{
if(ym_mode==1) //电压
{
t=ad_value_D;
t=t/100.0;
sprintf(arry,"Voltage:%.2fV",t);
sendstring(arry);
}
else if(ym_mode==2)//温度
{
// sprintf(arry,"TEMP:%d.%d℃",wendu_value/10,wendu_value%10);
// sendstring(arry);
t=wendu_value;
t=t/10.0;
sprintf(arry,"TEMP:%.1f℃",t);
sendstring(arry);
}
}
}
void keysong(unsigned char keydat)
{
if(keydat==4)
{
}
}
//==============================================================================================================================
void ledhandle()
{
P2&=0x1f;P0=0xff;
select573(4);
P0=led_num;
P2&=0x1f;P0=0xff;
}
void jdq_fmq_handle()
{
P2&=0x1f;P0=0x00;
select573(5);
P0=jdq_num;
P2&=0x1f;P0=0xff;
}
//==================中断函数=============================================================================================
void timer0()interrupt 1
{
ledhandle();
jdq_fmq_handle();
keyscan();
yemian();
display();
ad_t++;
if(ad_t>=500)
{
ad_t=0;
ad_flag=1;
wendu_flag=1;
}
if(l1_flag==1)
{
led_num=led_num&0xfe;
}
else if(l1_flag==0)
{
led_num=led_num|0x01;
}
else
led_num=led_num|0x01;
if(l2_flag==1)
{
led_num=led_num&0xfd;
}
else if(l2_flag==0)
{
led_num=led_num|0x02;
}
else
led_num=led_num|0x02;
if(lock_flag==1)
{
l3_count++;
if(l3_count<100)
{
led_num=led_num&0xfb;
}
else if(l3_count>=100&&(l3_count<200))
{
led_num=led_num|0x04;
}
else if(l3_count==200)
{
l3_count=0;
}
}
//继电器
if(jdq_flag==1)
{
jdq_num=jdq_num|0x10;
}
else if(jdq_flag==0)
{
jdq_num=jdq_num&0xef;
}
//蜂鸣器
if(beep_flag==1)
{
jdq_num=jdq_num|0x40;
}
else if(beep_flag==0)
{
jdq_num=jdq_num&0xbf;
}
}
//===================main函数============================================================================================
void main()
{
allinit();
timer0init();
UartInit();
while(1)
{
keyhandle();
if(ad_flag==1)
{
ad_flag=0;
ad_value=pcf_ad();
ad_value_D=ad_value*1.9607;
}
else if(wendu_flag==1)
{
wendu_flag=0;
wendu_value=read_temperature();
}
if(ym_mode==2)//温度界面
{
l1_flag=1;
}
else l1_flag=0;
if(ym_mode==1)//电压界面
{
l2_flag=1;
}
else l2_flag=0;
if(wendu_value>=260)
{
jdq_flag=1;
}
else
{
jdq_flag=0;
}
if(ad_value_D>360)
{
beep_flag=1;
}
else
{
beep_flag=0;
}
}
}
void yemian()
{
if(ym_mode==1)
{
dsbuff[0]=11;
dsbuff[1]=2;
dsbuff[2]=10;
dsbuff[3]=10;
dsbuff[4]=10;
dsbuff[5]=ad_value_D/100;
dsbuff[6]=ad_value_D/10%10;
dsbuff[7]=ad_value_D%10;
}
else if(ym_mode==2)
{
dsbuff[0]=11;
dsbuff[1]=1;
dsbuff[2]=10;
dsbuff[3]=10;
dsbuff[4]=10;
dsbuff[5]=wendu_value/100;
dsbuff[6]=wendu_value/10%10;
dsbuff[7]=wendu_value%10;
}
}
#include "intrins.h"
#include "stc15f2k60s2.h"
#include "iic.h"
#define DELAY_TIME 5
//
sbit scl=P2^0;
sbit sda=P2^1;
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);
}
unsigned char pcf_ad()
{
unsigned char adt;
EA=0;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x03);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
adt=I2CReceiveByte();
I2CSendAck(1);
I2CStop();
EA=1;
return adt;
}
IIC.C函数
#include "intrins.h"
#include "stc15f2k60s2.h"
#include "iic.h"
#define DELAY_TIME 5
//
sbit scl=P2^0;
sbit sda=P2^1;
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);
}
unsigned char pcf_ad()
{
unsigned char adt;
EA=0;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x03);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
adt=I2CReceiveByte();
I2CSendAck(1);
I2CStop();
EA=1;
return adt;
}
onewire.c函数
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "stc15f2k60s2.h"
#include "onewire.h"
sbit DQ=P1^4;
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
int read_temperature()
{
unsigned char low,high;
unsigned int temp;
EA=0;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
EA=1;
temp=high<<8;
temp=temp|low;
return temp*0.625; //保留两位小数
}