蓝桥杯单片机 赛后资料整理(三)——IIC总线

蓝桥杯单片机 赛后资料整理(三)——IIC总线

  • 通用操作
    • 写操作
    • 顺序读操作
    • 随机读操作
  • 代码模板
    • FCP8591
      • 控制字的说明
      • 读电位器和光敏电阻
      • 输出电压
    • AT24C02

本文适用于 CT107D竞赛板+ IAP15转接板

通用操作

资料中提供了相对完整的IIC的库函数,所以,可以不用深入的了解IIC总线的时钟顺序。而以下是选手必须要了解的。
器件地址: 地址的前4位由器件的型号决定,后3位由A0 A1 A2三个引脚决定,在CT107DFCP8591的地址是0x90AT24C02的地址是0xa0
**读/写标志位:**器件地址的后一位为读写标志位,1为读操作,0为写操作。

写操作

蓝桥杯单片机 赛后资料整理(三)——IIC总线_第1张图片

顺序读操作

蓝桥杯单片机 赛后资料整理(三)——IIC总线_第2张图片

随机读操作

蓝桥杯单片机 赛后资料整理(三)——IIC总线_第3张图片

代码模板

FCP8591

FCP8591是一个用于数模相互转换的芯片。

控制字的说明

说明
7 0 置零
6 x D/A标志,1打开,0关闭
5 x 模拟信号的输入方式,与后一位一起使用,一般使用方式0
4 x
3 0 置零
2 x 自动增量标志,一般情况下置零,如果置位,则在每次A/D转换后,通道编号自动增加
1 x 设置通道编号,与后一位一起使用
0 x 通道0A/D引脚,通道1为光敏电阻,通道2为仪表放大器,通道3为电位器

读电位器和光敏电阻

#include 
#include 

#ifndef u8
#define u8 unsigned char
#endif 

u8 code font[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
u8 code y6=0xc0,y7=0xe0;
u8 dis[8];
unsigned int uval,lval;

void delay100us()		//@12.000MHz
{
	unsigned char i, j;

	i = 2;
	j = 39;
	do
	{
		while (--j);
	} while (--i);
}

//数码管显示
void display(){
	u8 i;

	dis[0]=0xff;					//不显示	
	dis[1]=font[uval/100%10]&0x7f;	//显示电位器的电压				
	dis[2]=font[uval/10%10];	
	dis[3]=font[uval%10];
	dis[4]=0xff;					//不显示
	dis[5]=font[lval/100%10]&0x7f;	//显示光敏电阻的电压	
	dis[6]=font[lval/10%10];
	dis[7]=font[lval%10];

	//数码管显示
	for(i=0;i<8;i++){
		P2&=0x1f;
		P0=1<<i;
		P2|=y6;
		P2&=0x1f;
		P0=dis[i];
		P2|=y7;
		delay100us();
		P0=0xff;//消隐
	}
	P2&=0x1f;
}

void uread(){//读电位器,随机读操作, 
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x03);
	IIC_WaitAck();
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	uval=IIC_RecByte();
	uval=uval*500.0/255;
	IIC_Stop();
}
void lread(){//读光敏电阻,随机读操作,
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x01);
	IIC_WaitAck();
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	lval=IIC_RecByte();
	lval=lval*500.0/255;
	IIC_Stop();
}
int main(){
	while(1){
		lread();
		uread();
		display();	
	}
}

输出电压

#include 
#include 

#ifndef u8
#define u8 unsigned char
#endif 

u8 code font[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
u8 code y6=0xc0,y7=0xe0;
u8 dis[8];
unsigned int out_val=300;//输出电压为3.00伏

void delay100us()		//@12.000MHz
{
	unsigned char i, j;

	i = 2;
	j = 39;
	do
	{
		while (--j);
	} while (--i);
}

//数码管显示
void display(){
	u8 i;

	dis[0]=0xff;					//不显示	
	dis[1]=0xff;			
	dis[2]=0xff;	
	dis[3]=0xff;
	dis[4]=0xff;				
	dis[5]=font[out_val/100%10]&0x7f;	//显示输出电压	
	dis[6]=font[out_val/10%10];
	dis[7]=font[out_val%10];

	//数码管显示
	for(i=0;i<8;i++){
		P2&=0x1f;
		P0=1<<i;
		P2|=y6;
		P2&=0x1f;
		P0=dis[i];
		P2|=y7;
		delay100us();
		P0=0xff;//消隐
	}
	P2&=0x1f;
}
void output(){//输出电压,写操作
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);
	IIC_WaitAck();
	IIC_SendByte(out_val*255.0/500);
	IIC_WaitAck();
	IIC_Stop();
}
int main(){
	while(1){
		output();
		display();	
	}
}

如果手边没有电压表的话,可以用短接片把A/D D/A引脚连接起来,这样自己测自己。以下是这个方式的代码

#include 
#include 

#ifndef u8
#define u8 unsigned char
#endif 

u8 code font[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
u8 code y6=0xc0,y7=0xe0;
u8 dis[8];
unsigned int u_val,out_val=472;//输出电压为4.72伏

void delay100us()		//@12.000MHz
{
	unsigned char i, j;

	i = 2;
	j = 39;
	do
	{
		while (--j);
	} while (--i);
}

//数码管显示
void display(){
	u8 i;

	dis[0]=0xff;					//不显示	
	dis[1]=font[u_val/100%10]&0x7f;			
	dis[2]=font[u_val/10%10];	
	dis[3]=font[u_val%10];
	dis[4]=0xff;				
	dis[5]=font[out_val/100%10]&0x7f;	//显示输出电压	
	dis[6]=font[out_val/10%10];
	dis[7]=font[out_val%10];

	//数码管显示
	for(i=0;i<8;i++){
		P2&=0x1f;
		P0=1<<i;
		P2|=y6;
		P2&=0x1f;
		P0=dis[i];
		P2|=y7;
		delay100us();
		P0=0xff;//消隐
	}
	P2&=0x1f;
}
void FCP(){//我测我自己,随机读操作
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);
	IIC_WaitAck();
	IIC_SendByte(out_val*255.0/500);
	IIC_WaitAck();
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	u_val=IIC_RecByte();
	u_val=u_val*500.0/255;
	IIC_Stop();
}
int main(){
	while(1){
		FCP();
		display();	
	}
}

AT24C02

AT24C02是一个可擦写的ROM芯片,断电后数据不丢失,它提供了256B的存储空间。其中,256B被分为32页,每页8个字节。在进行写操作的时候,一次最多只能写一页。
其代码功能如下:
按键表

1 2 3 存储1
4 5 6 读取1
7 8 9 存储2
0 撤销 清零 读取2

要求运用按键对数字进行操作,并在数码管上显示出来。能在EEPROM中存储两个数,并能读取出来。

#include 
#include 

#ifndef u8
#define u8 unsigned char
#endif 

u8 code font[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
u8 code y6=0xc0,y7=0xe0;
u8 dis[8],num[8]={0,0,0,0,0,0,0,0};

void delay100us()		//@12.000MHz
{
	unsigned char i, j;

	i = 2;
	j = 39;
	do
	{
		while (--j);
	} while (--i);
}
void delay300ms()		//@12.000MHz
{
	unsigned char i, j, k;

	i = 14;
	j = 174;
	k = 224;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void add_num(u8 val){//在末尾增加一位数
	u8 i;

	if(num[0]==0){
		for(i=0;i<7;i++)
			num[i]=num[i+1];
		num[7]=val;
	}
}
void dec_num(){//去掉末尾的一位数
	u8 i;

	for(i=7;i>0;i--)
		num[i]=num[i-1];
	num[0]=0;
}
//数码管显示
void display(){
	u8 i;

	for(i=0;i<8;i++)
		dis[i]=font[num[i]];
	for(i=0;dis[i]==font[0]&&i<7;i++)
		dis[i]=0xff;

	for(i=0;i<8;i++){
		P2&=0x1f;
		P0=1<<i;
		P2|=y6;
		P2&=0x1f;
		P0=dis[i];
		P2|=y7;
		delay100us();
		P0=0xff;//消隐
	}
	P2&=0x1f;
}
void rom_read(u8 addr){//读取数据,addr代表地址
	u8 i;

	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	for(i=0;i<8;i++){
		num[i]=IIC_RecByte();
		IIC_SendAck(i==7);
	}
	IIC_Stop();
}
void rom_write(u8 addr){//存入数据,addr代表地址
	u8 i;
	
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	for(i=0;i<8;i++){
		IIC_SendByte(num[i]);
		IIC_WaitAck();
	}
	IIC_Stop();
}
void scankey(){//按键设置
	u8 key,i;

	P42=0;P44=0;P3=0x0f;
	if(P3!=0x0f){
		delay100us();
		if(P3!=0x0f){
			key=P3;
			P3=0xf0;P42=1;P44=1;
			key|=P3;
			if(P42==0) key&=0xbf;
			if(P44==0) key&=0x7f;
			delay300ms();
			switch(key){
				//返回按键编号
				case 0x77:add_num(0);break;				//s4
				case 0x7e:add_num(1);break;				//s7
				case 0xbe:add_num(2);break;				//s11	  
				case 0xde:add_num(3);break;				//s15	
				case 0x7d:add_num(4);break;				//s6 
				case 0xbd:add_num(5);break;				//s10	 
				case 0xdd:add_num(6);break;				//s14
				case 0x7b:add_num(7);break;				//s5	
				case 0xbb:add_num(8);break;				//s9	
				case 0xdb:add_num(9);break;				//s13
				case 0xb7:dec_num();break;				//s8“撤销”
				case 0xd7:for(i=0;i<8;i++)num[i]=0;break;//s12 “清零”
				case 0xee:rom_write(0x00);break;		//s19 “存储1”
				case 0xed:rom_read(0x00);break;			//s18 “读取1”
				case 0xeb:rom_write(0x08);break;		//s17 “存储2”
				case 0xe7:rom_read(0x08);break;			//s16 “读取2”
			}
		}	
	}
}
int main(){
	while(1){
		scankey();
		display();	
	}
}

你可能感兴趣的:(第十届蓝桥杯赛后资料整理,蓝桥杯单片机)