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_h
static 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_h
void 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_h
void 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,即12T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xCC; //设定定时初值
TH1 = 0xFF; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
ES = 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();
}
}