【蓝桥杯单片机】6个IO进阶模块应用总结

蓝桥杯单片机

  • (一)【DS18B20温度传感器】
  • 数码管后三位显示当前环境温度
  • onewire.h
  • onewire.c
  • DS18B20.c
  • (二)【DS1302时钟】
  • 数码管显示时钟
  • ds1302.h
  • ds1302.c
  • smg.h
  • smg.c
  • DS1302时钟.c
  • (三)【NE555定时器与频率测量】
  • 数码管显示频率输出
  • (四)【IIC-PCF8951-A/D】
  • 数码管显示ADC电压数据
  • smg.h
  • smg.c
  • iic.h
  • iic.c
  • main.c
  • (五)【IIC-AT24C02】
  • 存储数据掉电不丢失
  • headfile.h
  • config.c
  • config.h
  • smg.c
  • smg.h
  • iic.c
  • iic.h
  • main.c
  • (六)【超声波测距】
  • (一)【DS18B20温度传感器】

    数码管后三位显示当前环境温度

    onewire.h

    #ifndef __ONEWIRE_H
    #define __ONEWIRE_H
    
    //unsigned char rd_temperature(void);  为避免出现警告,可删除此句
    //将onewire.c中除延时函数外的函数声明引入在此头文件中
    
    void Write_DS18B20(unsigned char dat);
    unsigned char Read_DS18B20(void);
    bit init_ds18b20(void);
    
    #endif
    
    

    onewire.c

    只需将官方所给的源码中调用的所有延时函数中的参数扩大10倍

    /*
      程序说明: 单总线驱动程序
      软件环境: Keil uVision 4.10 
      硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
      日    期: 2011-8-9
    */
    #include "reg52.h"
    
    sbit DQ = P1^4;  //单总线接口
    
    //单总线延时函数
    void Delay_OneWire(unsigned int t)  //STC89C52RC
    {
    	while(t--);
    }
    
    //通过单总线向DS18B20写一个字节
    void Write_DS18B20(unsigned char dat)
    {
    	unsigned char i;
    	for(i=0;i<8;i++)
    	{
    		DQ = 0;
    		DQ = dat&0x01;
    		Delay_OneWire(50);
    		DQ = 1;
    		dat >>= 1;
    	}
    	Delay_OneWire(50);
    }
    
    //从DS18B20读取一个字节
    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(50);
    	}
    	return dat;
    }
    
    //DS18B20设备初始化
    bit init_ds18b20(void)
    {
      	bit initflag = 0;
      	
      	DQ = 1;
      	Delay_OneWire(120);
      	DQ = 0;
      	Delay_OneWire(800);
      	DQ = 1;
      	Delay_OneWire(100); 
        initflag = DQ;     
      	Delay_OneWire(50);
      
      	return initflag;
    }
    
    
    
    
    
    
    
    

    DS18B20.c

    #include "reg52.h"
    #include "onewire.h"  //引入提供的底层驱动文件(头文件中需要进行修改)
    //#include "absacc.h" MM模式(存储扩展)
    unsigned char SMG_NODOT[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};  //无小数点段码
    unsigned char SMG_DOT[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};  //有小数点段码
    
    void Select_HC573(unsigned char channel)  //锁存器选择 
    {
    	switch(channel)
    	{
    		case 4: P2 = P2 & 0x1f | 0x80; break;  //LED控制
    		case 5: P2 = P2 & 0x1f | 0xa0; break;  //蜂鸣器、继电器
    		case 6: P2 = P2 & 0x1f | 0xc0; break;  //数码管com共阳端
    		case 7: P2 = P2 & 0x1f | 0xe0; break;  //数码管段码端
    	}
    }
    
    void SMG_bit(unsigned char pos, unsigned char dat)  //控制单个数码管显示
    {
    	Select_HC573(7);  //消影
    	P0 = 0xff;
    	
    	Select_HC573(6);  //显示位置
    	P0 = 0x01 << pos;
    	Select_HC573(7);  //显示内容
    	P0 = dat;
    }
    
    void SMG_DisplayAll(unsigned char dat)  //控制全部数码管显示
    {
    	Select_HC573(6);   //全部数码管的共阳端有效
    	P0 = 0xff;
    	Select_HC573(7);  //控制全部数码管的段码端
    	P0 = dat;
    }
    void SMG_Delay(unsigned char t)  //动态数码管刷新延时函数
    {
    	while(t--);
    }
    
    unsigned int temp = 0x0000;  //温度变量,16位无符号int整型
    void SMG_Display()  //数码管显示函数
    {
    	SMG_bit(7,SMG_NODOT[temp % 10]);  //三位数的最后一位
    	SMG_Delay(100);
    	SMG_bit(6,SMG_DOT[(temp % 100) / 10]);  //三位数的中间位,带小数点
    	SMG_Delay(100);
    	SMG_bit(5,SMG_NODOT[temp / 100]);  //三位数的第一位
    	SMG_Delay(100);
    	
    	SMG_bit(4,0xff);  //由于温度只需三位,故其余数码管位都不需显示内容
    	SMG_Delay(100);
    	SMG_bit(3,0xff);
    	SMG_Delay(100);
    	SMG_bit(2,0xff);
    	SMG_Delay(100);
    	SMG_bit(1,0xff);
    	SMG_Delay(100);
    	SMG_bit(0,0xff);
    	SMG_Delay(100);
    	
    	SMG_DisplayAll(0xff);  //消影
    }
    
    unsigned char LSB,MSB;  //定义低8位、高8位变量
    void Read_temp()  //读写温度
    {
    	init_ds18b20();  //复位
    	Write_DS18B20(0xcc);  //跳过ROM
    	Write_DS18B20(0x44);  //转换温度
    	
    	init_ds18b20();  //复位
    	Write_DS18B20(0xcc);  //跳过ROM
    	Write_DS18B20(0xbe);  //读暂存器
    	
    	//读取时,低位在前,高为在后
    	LSB = Read_DS18B20();  //读取低8位字节
    	MSB = Read_DS18B20();  //读取高8位字节
    	
    	init_ds18b20();  //复位,停止暂存器数据读取
    	
    	temp = MSB;  //先赋值高8位到低位上
    	temp = (temp << 8 ) + LSB;  //将LSB和MSB整合成为一个16位的整数(+就是|或)
    	
    	if((temp & 0xf800) == 0x0000)  //高5位判断采用结果是正温度(全是0)还是负温度
    	{
    		//正温度处理办法
    		//详细内容参考<https://www.xmf393.com/2019/08/18/20190801801/>
    		temp = temp >> 4;  //取出温度结果的整数部分
    		temp = temp * 10;  //放大10倍,然后加上小数部分
    		temp = temp + (LSB & 0x0f) * 0.625;
    	}
    }
    
    
    void Init_System()  //初始化关闭外设
    {
    	Select_HC573(5);
    	P0 = 0x00;
    	Select_HC573(4);
    	P0 = 0xff;
    }
    
    void main()
    {
    	Init_System();  //初始化关闭外设
    	while(1)
    	{
    		Read_temp();  //读写温度
    		SMG_Display();  //数码管显示
    	}
    }
    

    (二)【DS1302时钟】

    数码管显示时钟

    ds1302.h

    直接添加官方提供的底层驱动代码不需要修改

    #ifndef __DS1302_H
    #define __DS1302_H
    
    void Write_Ds1302(unsigned char temp);
    void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
    unsigned char Read_Ds1302_Byte( unsigned char address );
    #endif
    

    ds1302.c

    注意检查管脚是否匹配

    /*
      程序说明: DS1302驱动程序
      软件环境: Keil uVision 4.10 
      硬件环境: CT107单片机综合实训平台 8051,12MHz
      日    期: 2011-8-9
    */
    
    #include <reg52.h>
    #include <intrins.h>
    
    sbit SCK=P1^7;		
    sbit SDA=P2^3;		
    sbit RST = P1^3;   // DS1302复位												
    
    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);			
    }
    

    smg.h

    #ifndef _SMG_H
    #define _SMG_H
    
    code unsigned char SMG_NODOT[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
    code unsigned char SMG_DOT[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
    
    void Select_HC573(unsigned char channel);
    void SMG_bit(unsigned char pos,unsigned char dat);
    void SMG_all(unsigned char dat);
    void SMG_Delay(unsigned int t);
    	
    #endif
    

    smg.c

    #include "reg52.h"
    
    void Select_HC573(unsigned char channel)
    {
    	switch(channel)
    	{
    		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; 
    	}
    }
    
    void SMG_bit(unsigned char pos,unsigned char dat)
    {
    	Select_HC573(7);
    	P0 = 0xff;
    	Select_HC573(6);
    	P0 = 0x01 << pos;
    	Select_HC573(7);
    	P0 = dat;
    }
    
    void SMG_all(unsigned char dat)
    {
    	Select_HC573(6);
    	P0 = 0xff;
    	Select_HC573(7);
    	P0 = dat;
    }
    
    void SMG_Delay(unsigned int t)
    {
    	while(t--);
    }
    

    DS1302时钟.c

    #include "reg52.h"
    #include "ds1302.h"
    #include "smg.h"
    
    /*================读写地址=================*/
    unsigned char write_ds1302_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
    unsigned char read_ds1302_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
    unsigned char Time[7]={0x13,0x59,0x10,0x28,0x01,0x06,0x23};  //BCD码 23年1月28日 星期六 10:59:13
    
    
    /*============日历时钟参数设置函数========*/
    void DS1302_Config() 
    {
    	char i;
    	Write_Ds1302_Byte(0x8e,0x00);  //允许向内存写入数据
    	for(i = 0; i < 7; i++)   //写入7个字节的时间参数
    	{
    		Write_Ds1302_Byte(write_ds1302_address[i],Time[i]); 
    	}
    	Write_Ds1302_Byte(0x8e,0x80);  //禁止向内存写入数据
    }
    
    /*============日历时钟数据读取函数============*/
    void Read_Time()
    {
    	char i;
    	for(i = 0; i < 7; i++)
    	{
    		Time[i] = Read_Ds1302_Byte(read_ds1302_address[i]); 
    	}
    }
    
    /*==============数码管显示函数================*/
    void SMG_Display()
    {
    	SMG_bit(0,SMG_NODOT[Time[2] / 16]);
    	SMG_Delay(100);
    	SMG_bit(1,SMG_NODOT[Time[2] % 16]);
    	SMG_Delay(100);
    	
    	SMG_bit(2,0xbf); 
    	SMG_Delay(100);
    	
    	SMG_bit(3,SMG_NODOT[Time[1] / 16]);
    	SMG_Delay(100);
    	SMG_bit(4,SMG_NODOT[Time[1] % 16]);
    	SMG_Delay(100);
    	
    	SMG_bit(5,0xbf);
    	SMG_Delay(100);
    	
    	SMG_bit(6,SMG_NODOT[Time[0] / 16]);
    	SMG_Delay(100);
    	SMG_bit(7,SMG_NODOT[Time[0] % 16]);
    	SMG_Delay(100);
    	
    	SMG_all(0xff);
    }
     
    /*==============程序初始化关闭外设=============*/
    void Init_System()
    {
    	Select_HC573(5);
    	P0 = 0x00;
    	Select_HC573(4);
    	P0 = 0xff;
    }
    
    /*==================主函数=====================*/
    void main()
    {
    	Init_System();
    	DS1302_Config();
    	while(1)
    	{
    		Read_Time();
    		SMG_Display();
    	}
    }
    
    

    (三)【NE555定时器与频率测量】

    数码管显示频率输出

    数码管相关内容与上一个引用相同.c.h文件

    #include "reg52.h"
    #include "smg.h"
    
    void Init_System()
    {
    	Select_HC573(5);
    	P0 = 0x00;
    	Select_HC573(4);
    	P0 = 0xff;
    }
    
    void Init_Time()
    {
    	TH0 = 0xff;  //T0做计数器,用来计数
    	TL0 = 0xff;  //记一次数刚好溢出一次
    	
    	TH1 = (65535 - 50000 + 1) / 256;  //T1做定时器
    	TL1 = (65535 - 50000 + 1) % 256;  //定时时长50ms
    	
    	TMOD = 0x06;  //T0 8位自动重装 模式2;T1 16位自动重装 模式0
    	//0000 0110
    
    	ET0 = 1;
    	ET1 = 1;
    	EA = 1;
    	TR0 = 1;
    	TR1 = 1;
    }	
    	
    unsigned int count_f = 0;
    unsigned int dat_f = 0;
    unsigned char count_t = 0;
    void Service_Time0() interrupt 1
    {
    	count_f++;
    }
    	
    void Service_Time1() interrupt 3
    {
    	count_t++;
    	if(count_t == 20)  //50ms * 20 = 1s
    	{
    		dat_f = count_f;
    		count_f = 0;
    		count_t = 0;
    	}
    }
    
    void SMG_Display()
    {
    	SMG_bit(0,0x8e);  //显示F,表示频率测量
    	SMG_Delay(100);
    	
    	SMG_bit(1,0xff);  //空两个数码管
    	SMG_Delay(100);
    	SMG_bit(2,0xff);
    	SMG_Delay(100);
    	
    	if(dat_f > 9999)  //5位数
    	{
    		SMG_bit(3,SMG_NoDot[dat_f / 10000]);
    		SMG_Delay(100);
    	}
    	if(dat_f > 999)
    	{
    		SMG_bit(4,SMG_NoDot[(dat_f / 1000) % 10]);
    		SMG_Delay(100);
    	}
    	if(dat_f > 99)
    	{
    		SMG_bit(5,SMG_NoDot[(dat_f / 100) % 10]);
    		SMG_Delay(100);
    	}
    	if(dat_f > 9)
    	{
    		SMG_bit(6,SMG_NoDot[(dat_f / 10) % 10]);
    		SMG_Delay(100);
    	}
    
    	SMG_bit(7,SMG_NoDot[dat_f % 10]);
    	SMG_Delay(100);
    
    	SMG_all(0xff);  //消影
    }
    	
    void main()
    {	
    	Init_System();
    	Init_Time();
    	while(1)
    	{
    		SMG_Display();
    	}
    }
    	
    

    (四)【IIC-PCF8951-A/D】

    【点击此链接,立即学习小蜜蜂老师的PCF8591教程】

    数码管显示ADC电压数据

    上电时光敏电阻0x03 控制电压显示
    独立按键S4控制 电位器0x01 电压显示

    smg.h

    #ifndef _SMG_H
    #define _SMG_H
    
    unsigned char SMG_NoDot[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
    unsigned char SMG_Dot[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
    
    void Select_HC573(unsigned char channel);
    void SMG_Delay(unsigned char t);
    void SMG_Bit(unsigned char pos,unsigned char value);
    void SMG_All(unsigned char dat);
    	
    #endif
    

    smg.c

    #include "reg52.h"
    
    void Select_HC573(unsigned char channel)
    {
    	switch(channel)
    	{
    		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;
    	}
    }
    
    void SMG_Delay(unsigned char t)
    {
    	while(t--);
    }
    
    void SMG_Bit(unsigned char pos,unsigned char value)
    {
    	Select_HC573(7);
    	P0 = 0xff;
    	Select_HC573(6);
    	P0 = 0x01 << pos;
    	Select_HC573(7);
    	P0 = value;
    }
    
    void SMG_All(unsigned char dat)
    {
    	Select_HC573(6);
    	P0 = 0xff;
    	Select_HC573(7);
    	P0 = dat;
    }
    	
    

    iic.h

    在官方给的底层文件基础上添加

    unsigned char PCF8591_adc(unsigned char addr);  //新增adc函数
    void PCF8591_dac(unsigned char dat);			//新增dac函数
    

    iic.c

    在官方给的底层文件基础上添加

    unsigned char PCF8591_adc(unsigned char addr) 
    {
    	unsigned char tmp;
    	
    	IIC_Start();				//IIC总线起始信号	
    	
    	IIC_SendByte(0x90);			//PCF8591的写设备地址
    	IIC_WaitAck();				//等待从机应答
    	
    	IIC_SendByte(addr);			//写入PCF8591的控制字节
    	IIC_WaitAck();				//等待从机应答
    	
    	IIC_Stop(); 				//IIC总线停止信号
    	
    	IIC_Start();				//IIC总线起始信号
    	
    	IIC_SendByte(0x91);			//PCF8591的读设备地址
    	IIC_WaitAck();				//等待从机应答
    	
    	tmp = IIC_RecByte();		//读取PCF8591的数据 
    	IIC_SendAck(1);				//产生非应答信号
    	
    	IIC_Stop();					//IIC总线停止信号
    	return tmp;
    }
    
    void PCF8591_dac(unsigned char dat)
    {
    	IIC_Start();				//IIC总线起始信号	
    	
    	IIC_SendByte(0x90);			//PCF8591的写设备地址
    	IIC_WaitAck();				//等待从机应答
    	
    	IIC_SendByte(0x43);			//写入PCF8591的控制字节
    	IIC_WaitAck();				//等待从机应答
    
    	IIC_SendByte(dat);			//dat-输出dac数据
    	IIC_WaitAck();				//等待从机应答
    	
    	IIC_Stop();					//IIC总线停止信号
    }
    

    main.c

    #include "reg52.h"
    #include "iic.h"
    #include "smg.h"
    
    unsigned char dat = 0;
    unsigned char channel = 0;
    unsigned char stat = 0;
    sbit S4 = P3^3;
    
    void SMG_Display()
    {
    	SMG_Bit(0,0xbf);
    	SMG_Delay(500);
    	SMG_Bit(1,SMG_NoDot[channel]);
    	SMG_Delay(500);
    	SMG_Bit(2,0xbf);
    	SMG_Delay(500);
    	SMG_Bit(3,0xff);
    	SMG_Delay(500);
    	SMG_Bit(4,0xff);
    	SMG_Delay(500);
    	
    	SMG_Bit(5,SMG_NoDot[dat / 100]);
    	SMG_Delay(500);
    	SMG_Bit(6,SMG_NoDot[dat % 100 / 10]);
    	SMG_Delay(500);
    	SMG_Bit(7,SMG_NoDot[dat % 10]);
    	SMG_Delay(500);
    	
    	SMG_All(0xff);
    }
    
    void Init_System()
    {
    	Select_HC573(5);
    	P0 = 0x00;
    	Select_HC573(4);
    	P0 = 0xff;
    }
    
    void Key_Scan()
    {
    	if(S4 == 0)
    	{
    		SMG_Delay(100);
    		if(S4 == 0)
    		{
    			if(stat == 0)
    			{
    				stat = 1;
    				while(S4 == 0)
    				{
    					channel = 1;  
    					dat = PCF8591_adc(0x03);
    					SMG_Display();
    				}
    			}
    			else if(stat == 1)
    			{
    				stat = 0;
    				while(S4 == 0)
    				{
    					channel = 3;  
    					dat = PCF8591_adc(0x01);
    					SMG_Display();
    				}
    			}
    		}
    	}
    }
    
    void main()
    {
    	Init_System();
    	while(1)
    	{
    		Key_Scan();
    		if(stat == 0)  				//上电时stat=0,光敏电阻控制显示电压
    		{
    			channel = 1;  
    			dat = PCF8591_adc(0x01);
    			SMG_Display();
    			
    		}
    		else if(stat == 1)			//使用按键,电位器控制显示电压
    		{
    			channel = 3;  
    			dat = PCF8591_adc(0x03);
    			SMG_Display();
    		}
    	}
    }
    
    
    

    (五)【IIC-AT24C02】

    【点击此链接,立即学习小蜜蜂老师的AT24C02教程】

    存储数据掉电不丢失

    上电一次,数据改变一次
    此次锁存器与头文件也采用了模块化编程
    会出现2个PCD8951函数未调用的警告
    由于24C02与8951函数十分相似,可以照它的模式编写,所以8951函数我没有删除,直接从上一节工程中保留下来,写了却没有使用就会出现警告

    headfile.h

    #ifndef _HEADFILE_H
    #define _HEADFILE_H
    
    #include "reg52.h"		//引脚
    #include "config.h"		//锁存器、系统初始化
    #include "smg.h"		//数码管显示
    #include "iic.h"		//PCF8951、AT24C02
    
    #endif
    

    config.c

    #include "reg52.h"
    
    void Select_HC573(unsigned char channel)
    {
    	switch(channel)
    	{
    		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;
    	}
    }
    
    void Init_System()
    {
    	Select_HC573(5);
    	P0 = 0x00;
    	Select_HC573(4);
    	P0 = 0xff;	
    }
    

    config.h

    #ifndef _CONFIG_H
    #define _CONFIG_H
    
    void Select_HC573(unsigned char channel);
    void Init_System();
    
    #endif
    

    smg.c

    #include "reg52.h"
    #include "config.h"
    
    void SMG_Delay(unsigned char t)
    {
    	while(t--);
    }
    
    void SMG_Bit(unsigned char pos,unsigned char value)
    {
    	Select_HC573(7);
    	P0 = 0xff;
    	Select_HC573(6);
    	P0 = 0x01 << pos;
    	Select_HC573(7);
    	P0 = value;
    }
    
    void SMG_All(unsigned char dat)
    {
    	Select_HC573(6);
    	P0 = 0xff;
    	Select_HC573(7);
    	P0 = dat;
    }
    

    smg.h

    #ifndef _SMG_H
    #define _SMG_H
    
    code unsigned char SMG_NoDot[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
    code unsigned char SMG_Dot[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
    
    void SMG_Delay(unsigned char t);
    void SMG_Bit(unsigned char pos,unsigned char value);
    void SMG_All(unsigned char dat);
    
    #endif
    
    

    iic.c

    /*
      程序说明: IIC总线驱动程序
      软件环境: Keil uVision 4.10 
      硬件环境: CT107单片机综合实训平台 8051,12MHz
      日    期: 2011-8-9
    */
    
    #include "reg52.h"
    #include "intrins.h"
    
    #define DELAY_TIME 5
    
    #define SlaveAddrW 0xA0
    #define SlaveAddrR 0xA1
    
    //总线引脚定义
    sbit SDA = P2^1;  /* 数据线 */
    sbit SCL = P2^0;  /* 时钟线 */
    
    void IIC_Delay(unsigned char i)
    {
        do{_nop_();}
        while(i--);        
    }
    //总线启动条件
    void IIC_Start(void)
    {
        SDA = 1;
        SCL = 1;
        IIC_Delay(DELAY_TIME);
        SDA = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 0;	
    }
    
    //总线停止条件
    void IIC_Stop(void)
    {
        SDA = 0;
        SCL = 1;
        IIC_Delay(DELAY_TIME);
        SDA = 1;
        IIC_Delay(DELAY_TIME);
    }
    
    //发送应答
    void IIC_SendAck(bit ackbit)
    {
        SCL = 0;
        SDA = ackbit;  					// 0:应答,1:非应答
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        IIC_Delay(DELAY_TIME);
        SCL = 0; 
        SDA = 1;
        IIC_Delay(DELAY_TIME);
    }
    
    //等待应答
    bit IIC_WaitAck(void)
    {
        bit ackbit;
    	
        SCL  = 1;
        IIC_Delay(DELAY_TIME);
        ackbit = SDA;
        SCL = 0;
        IIC_Delay(DELAY_TIME);
        return ackbit;
    }
    
    //通过I2C总线发送数据
    void IIC_SendByte(unsigned char byt)
    {
        unsigned char i;
    
        for(i=0; i<8; i++)
        {
            SCL  = 0;
            IIC_Delay(DELAY_TIME);
            if(byt & 0x80) SDA  = 1;
            else SDA  = 0;
            IIC_Delay(DELAY_TIME);
            SCL = 1;
            byt <<= 1;
            IIC_Delay(DELAY_TIME);
        }
        SCL  = 0;  
    }
    
    //从I2C总线上接收数据
    unsigned char IIC_RecByte(void)
    {
        unsigned char i, da;
        for(i=0; i<8; i++)
        {   
        	SCL = 1;
    	IIC_Delay(DELAY_TIME);
    	da <<= 1;
    	if(SDA) da |= 1;
    	SCL = 0;
    	IIC_Delay(DELAY_TIME);
        }
        return da;    
    }
    
    
    unsigned char PCF8951_adc(unsigned char addr)
    {
    	unsigned char tmp;
    	IIC_Start();
    	IIC_SendByte(0x90);
    	IIC_WaitAck();
    	IIC_SendByte(addr);
    	IIC_WaitAck();
    	IIC_Stop();
    	
    	IIC_Start();
    	IIC_SendByte(0x91);
    	IIC_WaitAck();
    	tmp = IIC_RecByte();
    	IIC_SendAck(1);
    	IIC_Stop();
    	return tmp;
    }
    void PCF8951_dac(unsigned char dat)
    {
    	IIC_Start();	
    	IIC_SendByte(0x90);
    	IIC_WaitAck();
    	IIC_SendByte(0x43);
    	IIC_WaitAck();
    	IIC_SendByte(dat);
    	IIC_WaitAck();
    	IIC_Stop();
    }
    unsigned char AT24C02_read(unsigned char addr)
    {
    	unsigned char tmp;
    	IIC_Start();
    	IIC_SendByte(0xa0);
    	IIC_WaitAck();
    	IIC_SendByte(addr);
    	IIC_WaitAck();
    	IIC_Stop();
    	
    	IIC_Start();
    	IIC_SendByte(0xa1);
    	IIC_WaitAck();
    	tmp = IIC_RecByte();
    	IIC_SendAck(1);
    	IIC_Stop();
    	return tmp;
    }	
    void AT24C02_write(unsigned char addr,unsigned char date)
    {
    	IIC_Start();	
    	IIC_SendByte(0xa0);
    	IIC_WaitAck();
    	IIC_SendByte(addr);
    	IIC_WaitAck();
    	IIC_SendByte(date);
    	IIC_WaitAck();
    	IIC_Stop();
    }
    

    iic.h

    #ifndef _IIC_H
    #define _IIC_H
    
    void IIC_Start(void); 
    void IIC_Stop(void);  
    bit IIC_WaitAck(void);  
    void IIC_SendAck(bit ackbit); 
    void IIC_SendByte(unsigned char byt); 
    unsigned char IIC_RecByte(void); 
    
    unsigned char PCF8951_adc(unsigned char addr);
    void PCF8951_dac(unsigned char dat);
    	
    unsigned char AT24C02_read(unsigned char addr);
    void AT24C02_write(unsigned char addr,unsigned char date);
    
    #endif
    

    main.c

    #include "headfile.h"
    unsigned char dat1 = 0,dat2 = 0,dat3 = 0;
    
    void Delay(unsigned int t)
    {
    	while(t--);
    }
    
    void read_write()
    {
    	dat1 = AT24C02_read(0x01);
    	dat2 = AT24C02_read(0x03);
    	dat3 = AT24C02_read(0x05);
    	
    	dat1 = dat1 + 1;
    	dat2 = dat2 + 2;
    	dat3 = dat3 + 3;
    	
    	if(dat1 > 10)dat1 = 0;
    	if(dat2 > 20)dat2 = 0;
    	if(dat3 > 30)dat3 = 0;
    	
    	AT24C02_write(0x01, dat1);
    	Delay(3000);
    	AT24C02_write(0x03, dat2);
    	Delay(3000);
    	AT24C02_write(0x05, dat3);
    	Delay(3000);
    }
    
    void SMG_Display()
    {
    	SMG_Bit(0,SMG_NoDot[dat1 / 10]);
    	SMG_Delay(500);
    	SMG_Bit(1,SMG_NoDot[dat1 % 10]);
    	SMG_Delay(500);
    	
    	SMG_Bit(2,0xbf);
    	SMG_Delay(500);
    	
    	SMG_Bit(3,SMG_NoDot[dat2 / 10]);
    	SMG_Delay(500);
    	SMG_Bit(4,SMG_NoDot[dat2 % 10]);
    	SMG_Delay(500);
    	
    	SMG_Bit(5,0xbf);
    	SMG_Delay(500);
    	
    	SMG_Bit(6,SMG_NoDot[dat3 / 10]);
    	SMG_Delay(500);
    	SMG_Bit(7,SMG_NoDot[dat3 % 10]);
    	SMG_Delay(500);
    	
    	SMG_All(0xff);
    }
    
    
    void main()
    {
    	Init_System();
    	read_write();
    	while(1)
    	{
    		SMG_Display();
    		
    	}
    }
    

    (六)【超声波测距】

    (偷个小懒,国赛模块先放一放吧…

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【蓝桥杯单片机】6个IO进阶模块应用总结

    发表回复