蓝桥杯CT107D常用模块分享_51单片机组

@说明: 以下是大学期间参加蓝桥杯的远古代码,常见模块代码分享,因为是远古代码水平有限 

下文模块有DS1302、AT24C02、双目超声波测距、PCF8591、继电器和蜂鸣器。

按键 -> 按键消抖处理思路-CSDN博客

数码管 -> 51单片机_动态数码管_带小数点处理-CSDN博客

流水灯 -> 51单片机_3种方法_流水灯-CSDN博客


一. DS1302时钟

//=====================================================
#include "MAIN.H"
sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   
u8 data SetNum[] = {0,0,0,0,0,0,0};  //时间数组
//=====================================================
//@role   :存放写地址和读地址的合集
typedef data enum
{
  Seconds_W = 0X80,Seconds_R ,Minutes_W , Minutes_R ,Hour_W , Hour_R ,Data_W ,Data_R ,Month_W , Month_R ,Day_W , Day_R,Year_W ,  Year_R ,WP_W , WP_R ,
} Office;
//=====================================================
//@role    :设定时间
//十进制转BCD存入
void DS1302_SetTime()
{                      

	Write_Ds1302_Byte( WP_W ,0X00);                    // close write protect
	Write_Ds1302_Byte( Year_W,SetNum[0]/10*16+SetNum[0]%10);           // years
	Write_Ds1302_Byte( Month_W,SetNum[1]/10*16+SetNum[1]%10);         // months
	Write_Ds1302_Byte(  Data_W,SetNum[2]/10*16+SetNum[2]%10);          // data
	Write_Ds1302_Byte( Hour_W,SetNum[3]/10*16+SetNum[3]%10);           //  hours
	Write_Ds1302_Byte( Minutes_W,SetNum[4]/10*16+SetNum[4]%10);       // Minutes
	Write_Ds1302_Byte( Seconds_W,SetNum[5]/10*16+SetNum[5]%10);      // Senconds
	Write_Ds1302_Byte(  Day_W ,SetNum[6]/10*16+SetNum[5]%10);           // week (1-7)
	Write_Ds1302_Byte( WP_W,0X80);                      // up write protect	
}
//=====================================================
//@role    : 读取时间数组中的时间
//BCD转10进制读出
void DS1302_ReadTime()
{	     
     SetNum[0] = Read_Ds1302_Byte(Year_R)/16*10+Read_Ds1302_Byte(Year_R)%16;
	 SetNum[1] = Read_Ds1302_Byte(Month_R)/16*10+Read_Ds1302_Byte(Month_R)%16;
	 SetNum[2] = Read_Ds1302_Byte(Data_R)/16*10+Read_Ds1302_Byte(Data_R)%16;
     SetNum[3] = Read_Ds1302_Byte(Hour_R)/16*10+Read_Ds1302_Byte(Hour_R)%16;
	 SetNum[4] = Read_Ds1302_Byte(Minutes_R)/16*10+Read_Ds1302_Byte(Minutes_R)%16;
	 SetNum[5] = Read_Ds1302_Byte(Seconds_R)/16*10+Read_Ds1302_Byte(Seconds_R)%16;
	 SetNum[6] = Read_Ds1302_Byte(Day_R)/16*10+Read_Ds1302_Byte(Day_R)%16;
}	
//=====================================================

3e3a7bd1cd17403b9aa0ad696a01ac8b.png


二. AT2402存储,这个器件有写周期和写保护

//===============================================
#include "MAIN.H"
#define AT24C02_Address 0XA0        
//===============================================
//@role  :   写入一字节
//@detail  :  Address can be 0-255
void AT2C02_WriteByte(uchar Address,Data )
{	
	IIC_Start();                                    //开始
	IIC_SendByte(AT24C02_Address);//发送设备地址 ——写
	if(!IIC_WaitAck()){IIC_Stop();}        //如果没有寻址成功,停止
	IIC_SendByte(Address);                 //发送写入的地址
	IIC_WaitAck();                               //等待应答
	IIC_SendByte(Data);                       //发送写入的数据
	IIC_WaitAck();                                //等待应答
	IIC_Stop();                                      //停止
}
//===============================================
//@role  :  读出一字节数据
//@detail  :  address  can be 0-255;
uchar AT24C02_ReadByte(uchar Address)
{
	unsigned char Data;
	IIC_Start();                                          //开始
	IIC_SendByte(AT24C02_Address);     
	if(!IIC_WaitAck()){IIC_Stop();}
	IIC_SendByte(Address);
	IIC_WaitAck();
	IIC_Start();
	IIC_SendByte(AT24C02_Address|0X01);  //发送设备地址——读
	IIC_WaitAck();
	Data=IIC_RecByte();
	IIC_Ack(1);
	IIC_Stop();
	return Data;
}
//===============================================

 三. 双目超声波测距 

//============================================================
#include "MAIN.H"
sbit TD = P1^0;    			 //发射端
sbit RD = P1^1;   			 //接收端
u16 data DISTANCE;     			 //测量距离变量
//============================================================
//@role :定时器1初始化
void T1_INIT()		
{
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
    TH1=0; TL1=0;
	TF1 = 0;		    //清除TF1标志
}
//============================================================
//@role  : 每隔12us翻转一次IO口,RD口发送8个周期频率约为K40HZ的信号
//@detail: f = 1/T ,T = 24us,f =1/24 = 0.04MHZ
void RELAY_SEND()
{
	u8 i = 0;
	for(i=0;i<8;i++){ TD =! TD; DELAY_12US(); }
}
//============================================================
//@role :超声波模块初始化
void RELAY_INIT()
{		
		T1_INIT();                  //定时器1初始化     
	  RELAY_SEND();               //RD口发送8个周期频率约为K40HZ的信号
	  TR1 = 1;                    //定时器1开始计时
		while(RD==1 && TF1==0);     //等待接收口接收完整信号
	  TR1 = 0;                    //定时器1停止计时
		if(TF1==1)                  //若超出测量范围,即溢出,溢出标志位TF1=1
	  {
			//超出测量范围
	  }	
		else                        //若没超出测量范围
		{
			DISTANCE = TH1*255+TL1;
			DISTANCE = (uint)(DISTANCE*0.017);
		}
}
//============================================================

四. PCF8591AD&DA转换器,转换有时间间隔。遇到的比较坑的一点是读取多个通道时数据会乱,采取的办法是读两遍,只取第二遍的数据为有效数据

//========================================================================
#include "MAIN.H"
uchar Data = 0;
//========================================================================
//@role:显示AD单通道读取的数值
void PCF8591_SHOW()
{
	NIXIE_SET(1, Data/100);
	NIXIE_SET(2, Data%100/10);
	NIXIE_SET(3, Data%10);
}
//========================================================================
//@role  	:PCF8591,AD初始化函数
//@detail  : PCF8591_INIT(选择通道,选择模式);  AINX can be( 0X01 、0X02、0X03、0X04)
void PCF8591_AD_INIT(uchar AINX)
{
	IIC_Start();                                                       //开始信号
	IIC_SendByte(PCF8591_Address);                	    //发送IIC设备地址,(写)
	if(!IIC_WaitAck()){IIC_Stop();}     					    //0为应答,1为不应答,if no ACK即没有寻址成功,end
	
	IIC_SendByte(AINX);             		 			       //发送控制字节
	IIC_WaitAck();                             					    //等待应答
	IIC_Stop();                                  					    //停止信号
}	
//========================================================================
//@role  :   单通道AD读取
uchar PCF8591_AD_READ(void)
{
	IIC_Start();
	IIC_SendByte(PCF8591_Address | 0X01);             //发送IIC设备地址(读)
	if(!IIC_WaitAck()) {IIC_Stop(); return 0;}                //if没有寻址成功,返回0;
	
	IIC_RecByte();                                                    //接收两遍数据并舍弃第一遍数据
	IIC_Ack(1);                                                          //不应答
	Data = IIC_RecByte();
	IIC_Ack(0);
	IIC_Stop();
	return Data;
}
//========================================================================
//@role   :PCF8591,DA初始化函数
void PCF8591_DA_INIT(float Data)                   //0X40
{
    IIC_Start();                                                       //开始信号
	IIC_SendByte(PCF8591_Address);                	    //发送IIC设备地址,(写)
	if(!IIC_WaitAck()){IIC_Stop();}     					    //0为应答,1为不应答,if no ACK即没有寻址成功,end
	
	IIC_SendByte(0X40);             		 			       //发送控制字节
	IIC_WaitAck();          										//等待应答
	IIC_SendByte(255*(Data/5));                           
	IIC_WaitAck();
	IIC_Stop();    
}



五、 要求上电关闭蜂鸣器和继电器,两种方法

//=================================================================
#include <STC15F2K60S2.H>
//=================================================================	
//@role    :锁存开关
//@detail  :4——LED、5——蜂鸣器继电器、6——数码管段选、7——数码管位选
void switch_138(unsigned char location) 
{
	P27 = location/2/2%2;
	P26 = location/2%2;
	P25 = location%2;
}
//=================================================================
void main()
{
	switch_138(5);P0 &= 0XAF;switch_138(0);//上电默认关闭蜂鸣器和继电器
	while(1);
}
//=================================================================
	
//=================================================================
#include <STC15F2K60S2.H>
//=================================================================
//@role    :锁存开关
//@detail  :4——LED、5——蜂鸣器继电器、6——数码管段选、7——数码管位选
void switch_138(unsigned char location)//锁存器通道选择函数
{
	switch(location)
	{
		case 0:{P2&=0X1F;}break;//无   
		case 4:{P2&=0X1F;P2|=0X80;}break;//LED*8通道
		case 5:{P2&=0X1F;P2|=0XA0;}break;//蜂鸣器继电器通道
		case 6:{P2&=0X1F;P2|=0XC0;}break;//数码管位选端通道 
		case 7:{P2&=0X1F;P2|=0XE0;}break;//数码管段选端通道
	} 
}
//=================================================================
void main()
{
	switch_138(5);P0 &= 0XAF;//上电默认关闭蜂鸣器和继电器
	while(1);
}
//=================================================================
	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值