蓝桥杯单片机学习笔记(十四) V2026大模板源代码

蓝桥杯单片机学习笔记(十四) 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;
	}
}
相关推荐
大卡片3 小时前
TIM控制器原理
单片机·嵌入式硬件
Tech_D4 小时前
微米级的精准魔法:激光微加工,解锁高端制造新可能
人工智能·单片机·机器人·自动化·制造
咸甜适中4 小时前
rust语言学习笔记Trait(十)PartialOrd、Ord(大小比较)
笔记·学习·rust
小+不通文墨4 小时前
在树莓派中用*C语言*实现MQTT通信
c语言·经验分享·笔记·嵌入式硬件·学习
笨鸟先飞的橘猫4 小时前
skynet——服务发现学习
学习·服务发现
-To be number.wan4 小时前
算法日记 | C++ 结构体
数据结构·学习·算法
保安大队王队长4 小时前
对于单片机以及单片机的应用,要学的还有涉及到的电路都有哪些
单片机·嵌入式硬件
大连好光景4 小时前
Skills索引大全
学习·ai编程
大卡片4 小时前
时钟控制器原理
单片机·嵌入式硬件