国信长天单片机竞赛训练之通过iic光敏,电位器采样(五)

本次培训内容学iic,要求实现:

        开机显示光敏电阻的值,S4按键控制显示光敏电阻值,S5按键控制显示Rb2电位器的值,S8按键控制存数据进EEPROM,S9按键控制显示存入EEPROM的值。

代码如下:

具体原理可以参考教程:

蓝桥杯单片机比赛学习(全)_哔哩哔哩_bilibili

//main.c
#include "sys.h" 
#include "iic.h"


u16 count=0;
u8 key_temp=0;
u8 key_recall=0;//保留上一个按键的状态
u16 adc_val=0;
u8 flag=0;
u16 erom=255;
u8 s=0;
/*
本次作业:
开机显示光敏电阻的值,S4按键控制显示光敏电阻值,
S5按键控制显示Rb2电位器的值,
S8按键控制存数据进EEPROM,S9按键控制显示存入EEPROM的值。
*/

void delay5ms()
{
	unsigned char i,j;

	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

void main(){
	 
	
	stop_all();//关蜂鸣器等无关外设
	Timer0Init();
	write_DAC(erom);//默认写入
	while(1){
	   
		 key_temp=key_scan();
			
	    
		if(key_temp>0){
			key_recall=key_temp;
		}
		  DT[4]=key_recall;
	 if(!flag){//默认显示光感
		 adc_val=ReadADC(0x01);//0x01 光敏传感
		 smg_play(adc_val,1);
	 }
	 else if(flag==1){
		 adc_val=ReadADC(0x03);//0x01 光敏传感
		  smg_play(adc_val,1);
		 
	 }
	 
		 smg_play(erom,0);
		 
		 
	  
	 
		
		switch(key_recall){
			case(4)://s4显示光敏电阻
					flag=0;
					break;
			case(5)://s5显示Rb2电位器
					 
					 flag=1;
				
					break;
			default:
				break;
		}
 
		if(key_temp==8){
			AT24C02_WB(1,adc_val);delay5ms();//存当前值  延迟保证已写入epprom	
		}
		else if(key_temp==9){
			
				erom=AT24C02_RB(1);delay5ms();
		}
		
	 
}
	 
}


 void Time0() interrupt 1{
	  
	 count++;
	 if(count==6000){
		 
		 count=0;
		 
	 }
	 smg_show(DT[s],s);//段,位 3 1 10 2
	 if(++s==10){
		 s=0;
	 }
	 
	 
 }
//sys.c
#include "sys.h"
	
sbit buzzer=P0^6;
sbit rely=P0^4;
unsigned char  code smg_index[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x7f,0xbf};
u8 DT[]={10,10,10,10,10,10,10,10,10,10,10};

/*
关蜂鸣器,led,继电器,数码管段,位
*/
#define key_low 0x0f
#define key_high 0xf0
//u8 key_press=0;
 
	void stop_all(){
	 
	P0=0xff;
	P2=P2&0x1f|0x80;
	P2&=0x1f;
 
		
	P0=0;	
	P2=P2&0x1f|0xe0;
	P2&=0x1f;
	 
	P2=P2&0x1f|0xc0;
	P0=0;	
	P2&=0x1f;
	 
	P2=P2&0x1f|0xa0;	
	P04=0;
	P06=0;
 
	P2&=0x1f;
}  
 
/*
数码管显示
*/
 void smg_show(unsigned char du,unsigned char wei){//   DT[S]  s
	   
	P0=1<<wei;	  
	P2=(P2&0x1f)|0xc0;//位选
	P2=P2&0x1f;
	
	
	P0=smg_index[du];    //段选
	P2=(P2&0x1f)|0xe0;
	P2=P2&0x1f;
	 
 }
 void Timer0Init(void)		//100微秒@11.0592MHz  1ms
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	EA=1;
	ET0=1;//开启时钟
}

u8 key_scan(){
	 
  static key_state=0,key_return=0;   //每次返回值和状态进来不会重置
	u8 key_press;
	switch(key_state)
	{
		case 0:     //未按按键时的状态
			key_return=0;    //返回值置零
			P3=0x0f; P42=0; P44=0; 
			//key_return=0;
			key_press = P3&key_low;
			if(key_press != 0x0f)
				key_state=1;
			break;
		case 1:    //按键按下去后第一次进scan_key的状态,每按一次按键只会进来case 1一次
			P3=0x0f; P42=0; P44=0;
			key_press = P3&key_low;
			if(key_press != 0x0f)
			{
				if(key_press==0x0e) key_return=7;
				if(key_press==0x0d) key_return=6;
				if(key_press==0x0b) key_return=5;
				if(key_press==0x07) key_return=4;
				
				P3=0xf0; P42=1; P44=1;
				key_press = P3&key_high;
				if(key_press==0xe0) key_return+=12;
				if(key_press==0xd0) key_return+=8;
				if(P42==0) key_return+=4;		
				key_state = 2;
			}
			break;
		case 2:    //按键一直按着的状态
			P3=0x0f; P42=0; P44=0;
			key_press=P3&key_low;
			if(key_press == 0x0f)   //放开按键后key_state = 0回到case 0
			{
				key_state = 0;
			}
		default:
			break;
	}
	return key_return;
}
 void smg_play(u8 temp,bit dei){
	 if(dei){
	  if(temp>100){
		 DT[5]=temp/100;
		 DT[6]=temp/10%10;
			DT[7]=temp%10;
		 }
		 else if(temp<100){
			 DT[5]=0;
			 DT[6]=temp/10;
			 DT[7]=temp%10;
		 }
	 
 }
 else{
	 if(temp>100){
		 DT[0]=temp/100;
		 DT[1]=temp/10%10;
			DT[2]=temp%10;
		 }
		 else if(temp<100){
			 DT[0]=0;
			 DT[1]=temp/10;
			 DT[2]=temp%10;
		 }
	 
 }
 }
 





//sys.h
#ifndef __SYS_H_
#define __SYS_H_
 
#include "stc15f2k60s2.h"
 

typedef unsigned char u8;
typedef unsigned int u16;

 u8 DT[];
void smg_show(unsigned char du,unsigned char wei);
void stop_all();
void Timer0Init(void);
u8 key_scan();
void smg_play(u8 temp,bit dei);
#endif

//iic.h
#ifndef _IIC_H
#define _IIC_H


void AT24C02_WB(u8 ward,D);
u8 AT24C02_RB(u8 ward);

u8 ReadADC(u8 ain);
void write_DAC(u8 dat);
 

#endif

//iic.c
/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include "sys.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;    
}
//adc读取
u8 ReadADC(u8 ain)
{
	u8 Data;
	IIC_Start(); 
	IIC_SendByte(0x90); 
	IIC_WaitAck();  
	IIC_SendByte(ain); 
	IIC_WaitAck(); 
	IIC_Stop();  
	
	IIC_Start(); 
	IIC_SendByte(0x91); 
	IIC_WaitAck();  
	Data=IIC_RecByte(); 
	IIC_Stop();  
	return Data;
}


//EEPROM 写入
void AT24C02_WB(u8 ward,D)
{
	IIC_Start(); 
	IIC_SendByte(0xa0); 
	IIC_WaitAck();  
	IIC_SendByte(ward); 
	IIC_WaitAck(); 
	IIC_SendByte(D); 
	IIC_WaitAck(); 
	IIC_Stop();  
}

//EEPROM 读取
u8 AT24C02_RB(u8 ward)
{
	u8 D;
	IIC_Start(); 
	IIC_SendByte(0xa0); 
	IIC_WaitAck();  
	IIC_SendByte(ward); 
	IIC_WaitAck(); 
	IIC_Start(); 
	IIC_SendByte(0xa1); 
	IIC_WaitAck();
	D=IIC_RecByte();
	IIC_Stop();  
	return D;
}

void write_DAC(u8 dat)
{
	IIC_Start(); 
	IIC_SendByte(0x90); 
	IIC_WaitAck();  
	IIC_SendByte(0x40); 
	IIC_WaitAck(); 
	
	IIC_SendByte(dat); 
	IIC_WaitAck();  
	IIC_Stop();  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值