蓝桥杯单片机学习笔记(十四) V2026大模板源代码
温馨提示:本文内容源自米醋电子工作室培训课,由本人进行总结
为方便学习,现将大模板源代码写在这里,供大家参考。
main.c
c
/* 头文件声明区域 */
#include <STC15F2K60S2.H>
#include "Led.h"
#include "Seg.h"
#include "Init.h"
#include "Key.h"
#include "onewire.h"
#include "ds1302.h"
#include "iic.h"
#include "Ultrasound.h"
#include "Uart.h"
#include <stdio.h>
#include <string.h>
/* 变量声明区域 */
pdata unsigned char Led_Buf[8] = {1,0,1,0,1,0,1,0};
pdata unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};
pdata unsigned char Key_Slow_Down = 0;
pdata unsigned char Seg_Slow_Down = 0;
pdata unsigned char Seg_Pos = 0;
pdata unsigned int Key_Val = 0,Key_Old = 0,Key_Down = 0,Key_Up = 0;
pdata unsigned char Pwm_Count = 0;
pdata unsigned char Pwm_Compare = 1;
pdata unsigned char Seg_Disp_Mode = 0;
pdata unsigned int Temperature_100x = 0;
pdata unsigned char ucRtc[3] = {13,25,25};
bit Rtc_Format = 0;//默认24小时
pdata unsigned char ucRtc_date[4] = {26,5,20,3};
pdata unsigned int Ad1_100x = 0,Ad3_100x = 0,Da_Out_100x = 0;
pdata unsigned char EEPROM_write1[8] = {1,2,3,4,5,6,7,8};
pdata unsigned char EEPROM_write2[8] = {0};
pdata unsigned char EEPROM_read[8] = {0};
pdata unsigned int Distance = 0;
pdata unsigned char uart_data[30] = {0};
pdata unsigned char uart_index = 0;
pdata unsigned char uart_tick = 0;
/* 信息处理函数 */
void Seg_Proc()
{
unsigned char temp_Mode = Seg_Disp_Mode + 1;
if(Seg_Slow_Down < 100) return;
Seg_Slow_Down = 0;
Rtc_Read(ucRtc);
Date_Read(ucRtc_date);
Temperature_100x = Temperature_Read() * 100;
Ad1_100x = Ad_Read(0x41) / 51.0f * 100;
Ad3_100x = Ad_Read(0x43) / 51.0f * 100;
Da_Write(Da_Out_100x/100.0f*51);
Distance = ultrasound_read();
switch(Seg_Disp_Mode)
{
case 0://pwm调光
Seg_Buf[1] = 10;
Seg_Buf[2] = 10;
Seg_Buf[3] = 10;
Seg_Buf[4] = 10;
Seg_Buf[5] = 10;
Seg_Buf[6] = (Pwm_Compare > 10)?Pwm_Compare / 10 % 10:10;
Seg_Buf[7] = Pwm_Compare % 10;
break;
case 1://Freq
Seg_Buf[1] = 10;
Seg_Buf[2] = 10;
Seg_Buf[3] = (Freq > 10000)?Freq / 10000 % 10:10;
Seg_Buf[4] = (Freq > 1000)?Freq / 1000 % 10:10;
Seg_Buf[5] = (Freq > 100)?Freq / 100 % 10:10;
Seg_Buf[6] = (Freq > 10)?Freq / 10 % 10:10;
Seg_Buf[7] = Freq % 10;
break;
case 2://温度
Seg_Buf[1] = 10;
Seg_Buf[2] = 10;
Seg_Buf[3] = 10;
Seg_Buf[4] = (Temperature_100x > 1000)?Temperature_100x / 1000 % 10:10;
Seg_Buf[5] = Temperature_100x / 100 % 10 + ',';
Seg_Buf[6] = Temperature_100x / 10 % 10;
Seg_Buf[7] = Temperature_100x % 10;
break;
case 3://时间
Seg_Buf[2] = ucRtc[0] / 10 % 10;
Seg_Buf[3] = ucRtc[0] % 10 + ',';
Seg_Buf[4] = ucRtc[1] / 10 % 10;
Seg_Buf[5] = ucRtc[1] % 10 + ',';
Seg_Buf[6] = ucRtc[2] / 10 % 10;
Seg_Buf[7] = ucRtc[2] % 10;
break;
case 4://年月日周
Seg_Buf[1] = ucRtc_date[0] / 10 % 10;
Seg_Buf[2] = ucRtc_date[0] % 10 + ',';
Seg_Buf[3] = ucRtc_date[1] / 10 % 10;;
Seg_Buf[4] = ucRtc_date[1] % 10 + ',';
Seg_Buf[5] = ucRtc_date[2] / 10 % 10;
Seg_Buf[6] = ucRtc_date[2] % 10 + ',';
Seg_Buf[7] = ucRtc_date[3] % 10;
break;
case 5://AD1,AD3
Seg_Buf[1] = Ad1_100x / 100 % 10 + ',';
Seg_Buf[2] = Ad1_100x / 10 % 10;
Seg_Buf[3] = Ad1_100x % 10;
Seg_Buf[4] = 10;
Seg_Buf[5] = Ad3_100x / 100 % 10 + ',';
Seg_Buf[6] = Ad3_100x / 10 % 10;
Seg_Buf[7] = Ad3_100x % 10;
break;
case 6://eeprom
Seg_Buf[0] = EEPROM_read[0] % 10;
Seg_Buf[1] = EEPROM_read[1] % 10;
Seg_Buf[2] = EEPROM_read[2] % 10;
Seg_Buf[3] = EEPROM_read[3] % 10;
Seg_Buf[4] = EEPROM_read[4] % 10;
Seg_Buf[5] = EEPROM_read[5] % 10;
Seg_Buf[6] = EEPROM_read[6] % 10;
Seg_Buf[7] = EEPROM_read[7] % 10;
break;
case 7://超声波
Seg_Buf[0] = Distance / 10000000 % 10;
Seg_Buf[1] = Distance / 1000000 % 10;
Seg_Buf[2] = Distance / 100000 % 10;
Seg_Buf[3] = Distance / 10000 % 10;
Seg_Buf[4] = Distance / 1000 % 10;
Seg_Buf[5] = Distance / 100 % 10;
Seg_Buf[6] = Distance / 10 % 10;
Seg_Buf[7] = Distance % 10;
break;
}
}
/* 按键处理函数 */
void Key_Proc()
{
if(Key_Slow_Down < 10) return;
Key_Slow_Down = 0;
if(P30 == 0) return;
Key_Val = Key_Read();
if(P30 == 0) return;
Key_Down = Key_Val & (Key_Val ^ Key_Old);
Key_Up = ~Key_Val & (Key_Val ^ Key_Old);
Key_Old = Key_Val;
// if(Key_Down == 1)//按键4
// if(++Seg_Disp_Mode == 8) Seg_Disp_Mode = 0;
switch(Key_Down)
{
case 1://s4
if(++Seg_Disp_Mode == 8) Seg_Disp_Mode = 0;
break;
case 6://S5和S6同时按下
Pwm_Compare = (Pwm_Compare == 0)?0:--Pwm_Compare;
break;
case 8://s7
Pwm_Compare = (Pwm_Compare > 9)?9:++Pwm_Compare;
break;
case 16://s8
Rtc_Format ^= 1;
Hour_Format(Rtc_Format);
break;
case 32://S9
EA = 0;
EEPROM_Write(EEPROM_write1,0,8);
EA = 1;
break;
case 64://s10
EA = 0;
EEPROM_Write(EEPROM_write2,0,8);
EA = 1;
break;
case 128://s11
EA = 0;
EEPROM_Read(EEPROM_read,0,8);
EA = 1;
break;
}
}
//串口中断服务函数
void Uart1_Isr(void) interrupt 4
{
if (RI) //检测串口1接收中断
{
uart_tick = 0;//连续10秒没接收到信息,就说明接收完了
uart_data[uart_index++] = SBUF;
RI = 0; //清除串口1接收中断请求位
}
}
//串口处理函数
void uart_proc()
{
if(uart_index == 0) return;//没接收到东西直接返回
if(uart_tick < 10) return;
printf("%s",uart_data);
memset(uart_data,0,uart_index);
uart_index = 0;
}
/* 定时器0初始化函数 */
void Timer0_Init(void) //1微秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05;
TL0 = 0x00; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
/* 定时器1中断服务函数 */
void Timer1_Isr(void) interrupt 3
{
Seg_Slow_Down++;
Key_Slow_Down++;
uart_tick++;
if(++Timer_200ms > 198)
{
Freq = (TH0 << 8) | TL0;
Timer_200ms = 0;
Freq *= 5;
TH0 = TL0 = 0;
}
if(++Seg_Pos == 8) Seg_Pos = 0;
if(Seg_Buf[Seg_Pos] > 20)
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]-',',1);
else
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],0);
if(++Pwm_Count == 10) Pwm_Count = 0;
if(Pwm_Compare > Pwm_Count)
Led_Disp(Led_Buf);
else
Led_Off();
}
/* 定时器1初始化函数 */
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
EA = 1;
}
/* Main */
void main()
{
System_Init();
EEPROM_Read(EEPROM_read,0,8);
ds18b20_setResoluation(4);
Rtc_Set(ucRtc);
Date_Set(ucRtc_date);
Uart1_Init();
Timer1_Init();
Timer0_Init();
while(1)
{
Key_Proc();
Seg_Proc();
uart_proc();
}
}
Led.c
c
#include "Led.h"
idata unsigned char temp_1 = 0x00;
idata unsigned char temp_1_old = 0xff;
void Led_Disp(unsigned char *ucLed)
{
temp_1 = 0x00;
temp_1 = ucLed[0] << 0 | ucLed[1] << 1 | ucLed[2] << 2 | ucLed[3] << 3 |
ucLed[4] << 4 | ucLed[5] << 5 | ucLed[6] << 6 | ucLed[7] << 7;
if(temp_1 != temp_1_old)
{
P0 = ~temp_1;
P2 = P2 & 0x1f | 0x80;
P2 &= 0x1f;
temp_1_old = temp_1;
}
}
void Led_Off()
{
P0 = 0xff;
P2 = P2 & 0x1f | 0x80;
P2 &= 0x1f;
temp_1_old = 0x00;
}
idata unsigned char temp_2 = 0x00;
idata unsigned char temp_2_old = 0x00;
//注意:此处的temp_2_old由0xff修改为0x00
//蜂鸣器
void Beep(bit enable)
{
if(enable)
temp_2 |= 0x40;
else
temp_2 &= ~0x40;
//需要某一位,把某一位或1,不需要某一位,把某一位与0
if(temp_2 != temp_2_old)
{
P0 = temp_2;
P2 = P2 & 0x1f | 0xa0;
P2 &= 0x1f;
temp_2_old = temp_2;
}
}
//继电器
void Relay(bit enable)
{
if(enable)
temp_2 |= 0x10;
else
temp_2 &= ~0x10;
//需要某一位,把某一位或1,不需要某一位,把某一位与0
if(temp_2 != temp_2_old)
{
P0 = temp_2;
P2 = P2 & 0x1f | 0xa0;
P2 &= 0x1f;
temp_2_old = temp_2;
}
}
//电机
void MOTOR(bit enable)
{
if(enable)
temp_2 |= 0x20;
else
temp_2 &= ~0x20;
//需要某一位,把某一位或1,不需要某一位,把某一位与0
if(temp_2 != temp_2_old)
{
P0 = temp_2;
P2 = P2 & 0x1f | 0xa0;
P2 &= 0x1f;
temp_2_old = temp_2;
}
}
Key.c
c
#include "Key.h"
unsigned int Key_Read()
{
unsigned int Key_State = 0;
P44 = 0;P42 = 1;P35 = 1;//P34 = 1;
if(P33 == 0) Key_State |= (1 << 0);
if(P32 == 0) Key_State |= (1 << 1);
if(P31 == 0) Key_State |= (1 << 2);
if(P30 == 0) Key_State |= (1 << 3);
P44 = 1;P42 = 0;P35 = 1;//P34 = 1;
if(P33 == 0) Key_State |= (1 << 4);
if(P32 == 0) Key_State |= (1 << 5);
if(P31 == 0) Key_State |= (1 << 6);
if(P30 == 0) Key_State |= (1 << 7);
P44 = 1;P42 = 1;P35 = 0;//P34 = 1;
if(P33 == 0) Key_State |= (1 << 8);
if(P32 == 0) Key_State |= (1 << 9);
if(P31 == 0) Key_State |= (1 << 10);
if(P30 == 0) Key_State |= (1 << 11);
//
// P44 = 1;P42 = 1;P35 = 1;//P34 = 0;
// if(P33 == 0) Key_State |= (1 << 12);
// if(P32 == 0) Key_State |= (1 << 13);
// if(P31 == 0) Key_State |= (1 << 14);
// if(P30 == 0) Key_State |= (1 << 15);
P44 = 1;P42 = 1;P35 = 1;//P34 = 1;
return Key_State;
}
Seg.c
c
#include "Seg.h"
pdata unsigned char Seg_Dula[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff
};
void Seg_Disp(unsigned char wela,unsigned char dula,bit point)
{
//消影
P0 = 0xff;
P2 = P2 & 0x1f | 0xe0;
P2 &= 0x1f;
P0 = 0x01 << wela;
P2 = P2 & 0x1f | 0xc0;
P2 &= 0x1f;
P0 = Seg_Dula[dula];
if(point)
P0 &= 0x7f;
P2 = P2 & 0x1f | 0xe0;
P2 &= 0x1f;
}
Init.c
c
#include "Init.h"
void System_Init()
{
P0 = 0xff;
P2 = P2 & 0x1f | 0x80;
P2 &= 0x1f;
P0 = 0x00;
P2 = P2 & 0x1f | 0xa0;
P2 &= 0x1f;
}
ds1302.c
c
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "ds1302.h"
#include <intrins.h>
sbit SCK = P1 ^ 7;
sbit SDA = P2 ^ 3;
sbit RST = P1 ^ 3;
//
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
void Rtc_Set(unsigned char *ucRtc)
{
Write_Ds1302_Byte(0x8e,0x00);
Write_Ds1302_Byte(0x84,ucRtc[0]/10*16 + ucRtc[0]%10);
Write_Ds1302_Byte(0x82,ucRtc[1]/10*16 + ucRtc[1]%10);
Write_Ds1302_Byte(0x80,ucRtc[2]/10*16 + ucRtc[2]%10);
Write_Ds1302_Byte(0x8e,0x80);
}
void Rtc_Read(unsigned char *ucRtc)
{
unsigned char temp1[3],temp2[3];
do
{
temp1[0] = Read_Ds1302_Byte(0x85);
temp1[1] = Read_Ds1302_Byte(0x83);
temp1[2] = Read_Ds1302_Byte(0x81);
temp2[0] = Read_Ds1302_Byte(0x85);
temp2[1] = Read_Ds1302_Byte(0x83);
temp2[2] = Read_Ds1302_Byte(0x81);
}while(temp1[0] != temp2[0] || temp1[1] != temp2[1] || temp1[2] != temp2[2]);
if(temp1[0] & 0x80) //12小时进制
ucRtc[0] = (temp1[0] & 0x10)/16*10 + temp1[0]%16;
else //24小时进制
ucRtc[0] = (temp1[0] & 0x30)/16*10 + temp1[0]%16;
ucRtc[1] = temp1[1]/16*10 + temp1[1]%16;
ucRtc[2] = temp1[2]/16*10 + temp1[2]%16;
}
//时间进制转换 0-12h 1-24h
void Hour_Format(bit mode)
{
unsigned char hour_reg,hour_dec;
unsigned char is_pm = 0;//判断是不是下午
unsigned char is_12 = 0;//判断是否开启12小时制
hour_reg = Read_Ds1302_Byte(0x85);//读取小时寄存器内容
is_12 = (hour_reg & 0x80)?1:0;//是否为12小时制?是取1,不是取0
if(is_12)//12小时制
{
is_pm = (hour_reg & 0x20);//这一位是1,下午,这一位是0,上午
hour_dec = (hour_reg & 0x10)/16*10 + hour_reg%16;
}
else//24小时制
{
hour_dec = (hour_reg & 0x30)/16*10 + hour_reg%16;
}
Write_Ds1302_Byte(0x8e,0x00);
if(mode == 1)//切换成12小时进制
{
if(!is_12)//如果不是12进制
{
if(hour_dec == 0) {hour_dec = 12;is_pm = 0;}//24小时进制的0点
else if(hour_dec < 12) is_pm = 0;//上午
else if(hour_dec == 12) is_pm = 1;//中午
else {hour_dec -= 12;is_pm = 1;}//下午
}
Write_Ds1302_Byte(0x84,0x80 | (is_pm?0x20:0x00) | hour_dec/10*16+hour_dec%10);
//写入(pm/am),真实时间
}
else
{
if(is_12)//12-24
{
if(is_pm)//下午
{
if(hour_dec != 12)
hour_dec += 12;
}
else//上午
{
if(hour_dec == 12)
hour_dec = 0;//12am=00:00
}
}
Write_Ds1302_Byte(0x84,hour_dec/10*16 + hour_dec%10);
}
}
//年月日周的写入
void Date_Set(unsigned char *ucRtc)
{
Write_Ds1302_Byte(0x8e,0x00);
Write_Ds1302_Byte(0x8c,ucRtc[0]/10*16 + ucRtc[0]%10);//年
Write_Ds1302_Byte(0x88,ucRtc[1]/10*16 + ucRtc[1]%10);//月
Write_Ds1302_Byte(0x86,ucRtc[2]/10*16 + ucRtc[2]%10);//日
Write_Ds1302_Byte(0x8a,ucRtc[3]/10*16 + ucRtc[3]%10);//周
Write_Ds1302_Byte(0x8e,0x80);
}
//年月日周的读取
void Date_Read(unsigned char *ucRtc)
{
unsigned char temp[4];
temp[0] = Read_Ds1302_Byte(0x8d);
temp[1] = Read_Ds1302_Byte(0x89);
temp[2] = Read_Ds1302_Byte(0x87);
temp[3] = Read_Ds1302_Byte(0x8b);
ucRtc[0] = temp[0]/16*10 + temp[0]%16;
ucRtc[1] = temp[1]/16*10 + temp[1]%16;
ucRtc[2] = temp[2]/16*10 + temp[2]%16;
ucRtc[3] = temp[3]/16*10 + temp[3]%16;
}
onewire.c
c
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#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;
}
float Temperature_Read()
{
unsigned char high1,low1,high2,low2;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
do{
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low1 = Read_DS18B20();
high1 = Read_DS18B20();
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low2 = Read_DS18B20();
high2 = Read_DS18B20();
}while(high1 != high2 || low1 != low2);
return (float)(high1 << 8 | low1) * 0.0625f;
}
//温度精度设置
void ds18b20_setResoluation(unsigned char res)
{
unsigned char config;
switch(res)
{
case 0://9位
config = 0x1f;
break;
case 1://10位
config = 0x3f;
break;
case 2://11位
config = 0x5f;
break;
default://12位
config = 0x7f;
break;
}
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x4e);
Write_DS18B20(0x00);
Write_DS18B20(0x00);
Write_DS18B20(config);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x48);
}
iic.c
c
/* # I2C代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "iic.h"
#include "intrins.h"
sbit sda = P2 ^ 1;
sbit scl = P2 ^ 0;
#define DELAY_TIME 10
void Delay5ms(void) //@12.000MHz
{
unsigned char data i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
//
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 Ad_Read(unsigned char addr)
{
unsigned char temp1,temp2;
do
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
temp1 = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
temp2 = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
}while(temp1 != temp2);
return temp1;
}
void Da_Write(unsigned char dat)
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x41);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
//EEPROM写入函数
//str:写入数据的数组,addr:写入数组的首地址,num:写入数据的数量
void EEPROM_Write(unsigned char *str,unsigned char addr,unsigned char num)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
while(num--)
{
I2CSendByte(*str++);
I2CWaitAck();
I2C_Delay(200);
}
I2CStop();
Delay5ms();
}
void EEPROM_Read(unsigned char *str,unsigned char addr,unsigned char num)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
while(num--)
{
*str++ = I2CReceiveByte();
if(num)
I2CSendAck(0);
else
I2CSendAck(1);
}
I2CStop();
}
ultrasound.c
c
#include "Ultrasound.h"
#include <intrins.h>
sbit us_tx = P1 ^ 0;
sbit us_rx = P1 ^ 1;
void Delay10us(void) //@12.000MHz
{
unsigned char data i;
_nop_();
_nop_();
i = 27;
while (--i);
}
unsigned int time;
unsigned int ultrasound_read()
{
CMOD = 0x00;
CH=CL=0;
us_tx = 1;
Delay10us();
us_tx = 0;
CR=1;
while((us_rx==1)&&(CF==0));
CR=0;
if(CF==0)
{
time=CH<<8 |CL;
//340m/s=34000cm/s=0.034cm/us
//s=t*v/2=0.034*t/2=0.017*t
return time*0.017;
}
else
{
CF = 0;
return 999;
}
}
Uart.c
c
#include "Uart.h"
#include <stdio.h>
void Uart1_Init(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0xE6; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES = 1; //使能串口1中断
EA = 1;
}
extern char putchar(char ch)
{
SBUF = ch;
while(TI == 0);
TI = 0;
return ch;
}
//串口变量声明
pdata unsigned char uart_data[30] = {0};
pdata unsigned char uart_index = 0;
pdata unsigned char uart_tick = 0;
//串口中断服务函数
void Uart1_Isr(void) interrupt 4
{
if (RI) //检测串口1接收中断
{
uart_tick = 0;//连续10秒没接收到信息,就说明接收完了
uart_data[uart_index++] = SBUF;
RI = 0; //清除串口1接收中断请求位
}
}
//串口处理函数
void uart_proc()
{
if(uart_index == 0) return;//没接收到东西直接返回
if(uart_tick < 10) return;
printf("%s",uart_data);
memset(uart_data,0,uart_index);
uart_index = 0;
}
//在定时器1,把uart_tick++
NE555
c
//定义变量
pdata unsigned int Freq = 0;
pdata unsigned char Timer_200ms = 0;
//定时器0调为计数模式
/* 定时器0初始化函数 */
void Timer0_Init(void) //1微秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05;
TL0 = 0x00; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
//在定时器1中断服务函数里测量频率
void Timer1_Isr(void) interrupt 3
{
//频率相关部分
if(++Timer_200ms > 198)
{
Freq = (TH0 << 8) | TL0;
Timer_200ms = 0;
Freq *= 5;
TH0 = TL0 = 0;
}
}