iic.c
/* # I2C代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.H>
#include "iic.h"
#include "intrins.h"sbit scl = P2^0;
sbit sda = P2^1;#define DELAY_TIME 5//
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);
}void Write_PCF8591(unsigned char dat)
{I2CStart();I2CSendByte(0x90);I2CWaitAck();I2CSendByte(0x40);I2CWaitAck();I2CSendByte(dat);I2CWaitAck();I2CStop();
}void Writr_AT24C02(unsigned char dat)
{I2CStart();I2CSendByte(0xa0);I2CWaitAck();I2CSendByte(0x00);I2CWaitAck();I2CSendByte(dat);I2CWaitAck();I2CStop();
}unsigned char Read_AT24C02()
{unsigned char temp;I2CStart();I2CSendByte(0xa0);I2CWaitAck();I2CSendByte(0x00);I2CWaitAck();I2CStart();I2CSendByte(0xa1);I2CWaitAck();temp = I2CReceiveByte();I2CSendAck(1);I2CStop();return temp;
}
iic.h
#ifndef __iic_h
#define __iic_hstatic void I2C_Delay(unsigned char n);
void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);
void Write_PCF8591(unsigned char dat);
void Writr_AT24C02(unsigned char dat);
unsigned char Read_AT24C02();#endif
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;
}unsigned int Read_temp()
{unsigned char LSB,MSB;unsigned int temp;init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0x44);init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0xbe);LSB = Read_DS18B20();MSB = Read_DS18B20();temp = MSB << 8 | LSB;return temp * 6.25;
}
onewire.h
#ifndef __onewire_h
#define __onewire_hvoid Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
unsigned int Read_temp();#endif
sys.c
#include <STC15F2K60S2.H>
#include "sys.h"
#include "intrins.h"void Delay12us() //@12.000MHz
{unsigned char i;_nop_();_nop_();i = 33;while (--i);
}void Delay_ms(unsigned int t) //@12.000MHz
{while(t--){unsigned char i, j;i = 12;j = 169;do{while (--j);} while (--i);}
}void Select_Hc573(char n)
{switch(n){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;
}void Sys_Init()
{P0 = 0x00;Select_Hc573(5);P0 = 0xff;Select_Hc573(4);
}void Select_Bit(unsigned char pos,dat)
{P0 = 0x01 << pos;Select_Hc573(6);P0 = dat;Select_Hc573(7);Delay_ms(1);P0 = 0xff;Select_Hc573(7);
}
sys.h
#ifndef __sys_h
#define __sys_hvoid Delay_ms(unsigned int t);
void Select_Hc573(char n);
void Sys_Init();
void Select_Bit(unsigned char pos,dat);
void Delay12us();#endif
main.c
#include <STC15F2K60S2.H>
#include "sys.h"
#include "onewire.h"
#include "iic.h"
#include "stdio.h"sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;
sbit C1 = P4^4;
sbit C2 = P4^2;
sbit C3 = P3^5;
sbit C4 = P3^4;code unsigned char SMG[] = { ~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F,~0x39,~0x38,~0x67,~0x73};sbit TX = P1^0;
sbit RX = P1^1;unsigned char i;
unsigned char key_val;//键值
unsigned int dis;//距离
unsigned int temp;//温度
unsigned char count=1;//变更次数
char param_temp = 30;//温度参数
char param_dis = 35;//距离参数
char param_temp_old = 30,param_dis_old = 35;
bit flag_10ms,flag_500ms;
bit mode;//大界面切换 0-数据界面 1-参数界面
unsigned char mode_dat;//数据界面切换 0-温度 1-距离 2-变更次数
bit mode_param;//参数界面切换 0-温度 1-距离
bit flag_dac_open = 1;
unsigned char str[10];
unsigned char Rec[10];
unsigned char index;//索引
unsigned char index_old;
unsigned char count1;void PCA_Init()
{CCON = 0;CMOD |= 0x08;
}void Send()//发送超声波
{for(i = 0;i < 8;i++){TX = 1;Delay12us();TX = 0;Delay12us();}CH = CL = 0;CR = 1;while(RX && !CF);CR = 0;if(!CF){dis = (CH << 8 | CL)* 0.017 / 12;}else{dis = 99;CF = 0;}
}void Display_temp()//温度界面
{Select_Bit(0,SMG[10]);Select_Bit(4,SMG[temp / 1000]);Select_Bit(5,SMG[temp /100 % 10] - 0x80);Select_Bit(6,SMG[temp / 10 % 10]);Select_Bit(7,SMG[temp % 10]);
}void Display_dis()//距离界面
{Select_Bit(0,SMG[11]);Select_Bit(6,SMG[dis / 10]);Select_Bit(7,SMG[dis % 10]);
}void Display_count()//变更次数界面
{Select_Bit(0,SMG[12]);if(count > 99) Select_Bit(5,SMG[count / 100]);if(count > 9) Select_Bit(6,SMG[count / 10]);Select_Bit(7,SMG[count % 10]);
}void DIsplay_Param_temp()//温度参数界面
{Select_Bit(0,SMG[13]);Select_Bit(3,SMG[1]);Select_Bit(6,SMG[param_temp / 10]);Select_Bit(7,SMG[param_temp % 10]);
}void DIsplay_Param_dis()//距离参数界面
{Select_Bit(0,SMG[13]);Select_Bit(3,SMG[2]);Select_Bit(6,SMG[param_dis / 10]);Select_Bit(7,SMG[param_dis % 10]);
}void Timer2Init(void) //10毫秒@12.000MHz
{AUXR &= 0xFB; //定时器时钟12T模式T2L = 0xF0; //设置定时初值T2H = 0xD8; //设置定时初值AUXR |= 0x10; //定时器2开始计时IE2 = 1 << 2;
}void Timer2_isr() interrupt 12
{flag_10ms = 1;if(++count1 > 100){count1 = 0;flag_500ms = 1;}
}unsigned char Key_Scan()//按键扫描获取键值
{static unsigned int cnt13 = 0;static unsigned int cnt12 = 0;static unsigned char cnt16 = 0;static unsigned char cnt17 = 0;if(flag_10ms)//10ms扫描一次{R3 = 0;R1 = R2 = R4 = C1 = C2 = C3 = C4 = 1;if(C3 == 0) {cnt13++;if(cnt13 > 100) temp = 130;}if(C3 == 1){if(cnt13 > 2 && cnt13 < 100) temp = 13;cnt13 = 0;}if(C4 == 0) cnt17++;if(C4 == 1){if(cnt17 > 2) temp = 17;cnt17 = 0;}R4 = 0;R1 = R2 = R3 = C1 = C2 = C3 = C4 = 1;if(C3 == 0) {cnt12++;if(cnt12 > 100) temp = 120; }if(C3 == 1){if(cnt12 > 2 && cnt12 < 100) temp = 12;cnt12 = 0;}if(C4 == 0) cnt16++;if(C4 == 1){if(cnt16 > 2) temp = 16;cnt16 = 0;}flag_10ms = 0;}return temp;
}
void Key_Pro()//键值处理函数
{switch(key_val){case 12 :if(!mode){if(++mode_dat > 2) mode_dat = 0;}else mode_param = ~mode_param;break;case 13:mode = ~mode;if(!mode) mode_param = 0;else mode_dat = 0;if(!mode)//数据的存储{if(param_temp_old != param_temp){count++;param_temp_old = param_temp; }else if(param_dis_old != param_dis){count++;param_dis_old = param_dis; }Writr_AT24C02(count);}break;case 16:if(mode){if(!mode_param){ param_temp -= 2;if(param_temp < 0) param_temp = 98;}else{param_dis -= 5;if(param_dis < 0) param_dis = 95;}}break;case 17:if(mode){if(!mode_param){ param_temp += 2;if(param_temp > 99) param_temp = 0;}else{param_dis += 5;if(param_dis > 99) param_dis = 0;}}break;case 120:count = 0;break;case 130:flag_dac_open ^= 1;break; }
}void Display()//数码管显示函数
{if(!mode){switch(mode_dat){case 0:Display_temp();break;case 1:Display_dis();break;case 2:Display_count();break;}}else{if(!mode_param) DIsplay_Param_temp();else DIsplay_Param_dis();}
}void UartInit(void) //4800bps@12.000MHz
{SCON = 0x50; //8位数据,可变波特率AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12TAUXR &= 0xFE; //串口1选择定时器1为波特率发生器TMOD &= 0x0F; //设定定时器1为16位自动重装方式TL1 = 0xCC; //设定定时初值TH1 = 0xFF; //设定定时初值ET1 = 0; //禁止定时器1中断TR1 = 1; //启动定时器1ES = 1;
}void Send_Byte(unsigned char dat)
{SBUF = dat;while(!TI);TI = 0;
}void Send_String(unsigned char *dat)
{while(*dat != '\0')Send_Byte(*dat++);
}void Uart_isr() interrupt 4
{if(RI){Rec[index] = SBUF;index++;RI = 0;}
}
bit ok,error_flag;
void Uart_Pro()
{
// if(flag_500ms)
// {
// if(index > 0)
// {
// if(index_old != index)//上一次的索引和这一次的索引不一样的话就刷新,且不进入判断
// {
// index_old = index;//刷新
// ok = 0;// 1-进行字符判断 0-不进行判断
// }
// else ok = 1;
// }
// flag_500ms = 0;
// }
// if(ok)
// {
// if(index == 4)
// {
// if(Rec[0] == 'S' && Rec[1] == 'T' && Rec[2] == '\r' && Rec[3] == '\n')
// {
// sprintf(str,"$%d,%.2f\r\n",dis,((float)temp )/ 100);
// Send_String(str);
// sprintf(str,"\r\n");
// Send_String(str);
// }
// else flag = 1;
// }
// else if(index == 6)
// {
// if(Rec[0] == 'P' && Rec[1] == 'A' && Rec[2] == 'R' && Rec[3] == 'A' && Rec[4] == '\r' && Rec[5] == '\n')
// {
// sprintf(str,"#%d,%d\r\n",(int)param_temp,(int)param_dis);
// Send_String(str);
// }
// else flag = 1;
// }
// else flag = 1;
// if(flag)
// {
// sprintf(str,"ERROR\r\n");
// Send_String(str);
// flag=0;
// }
// index = 0;
// ok = 0;
// }if(Rec[index - 1] == '\n'){if(index == 4){if(Rec[0] == 'S' && Rec[1] == 'T' && Rec[2] == '\r' && Rec[3] == '\n'){sprintf(str,"$%d,%.2f\r\n",dis,((float)temp )/ 100);Send_String(str);}}else if(index == 6){if(Rec[0] == 'P' && Rec[1] == 'A' && Rec[2] == 'R' && Rec[3] == 'A' && Rec[4] == '\r' && Rec[5] == '\n'){sprintf(str,"#%d,%d\r\n",(int)param_temp,(int)param_dis);Send_String(str);}}else{sprintf(str,"ERROR\r\n");Send_String(str);}index = 0;}
}void Dac_Pro()
{if(flag_dac_open){if(dis <= param_dis) Write_PCF8591(2 * 51);else Write_PCF8591(4 * 51);}else Write_PCF8591(20);
}void Led(unsigned char addr,enable)
{static unsigned char temp = 0x00;static unsigned char temp_old = 0xff;if(enable) temp |= 0x01 << addr;else temp &= ~(0x01 << addr);if(temp != temp_old){P0 = ~temp;Select_Hc573(4);temp_old = temp;}
}void Led_Pro()
{if( ((float)temp) / 100 > param_temp ) Led(0,1);else Led(0,0);if(dis < param_dis) Led(1,1);else Led(1,0);if(flag_dac_open) Led(2,1);else Led(2,0);
}void main()
{Sys_Init();PCA_Init();Timer2Init();UartInit();EA = 1;Read_temp();Delay_ms(750);count = Read_AT24C02();while(1){if(flag_500ms){Send();flag_500ms = 0;}temp = Read_temp();key_val = Key_Scan();Uart_Pro();Key_Pro();Display();Dac_Pro();Led_Pro();}
}