当前位置:   article > 正文

05 蓝桥杯单片机设计与开发_基础模块_AT24C02

蓝桥杯单片机设计与开发

一、前言

04 蓝桥杯单片机设计与开发_基础模块_PCF8591-CSDN博客,承接上文,本文将继续介绍剩余蓝桥杯涉及模块(AT24C02、PWM、串口通信、NE555以及超声波测距),为大家做出详细编程指导。

二、AT24C02 存储模块

笔者将基于蓝桥杯官方给的赛点资源包(蓝桥杯单片机设计与开发_赛点资源数据包)进行编程,为大家讲解编程调用各语句的含义,帮助大家编写温度传感器的程序,也便于大家记忆。

1、导入底层驱动代码

首先,创建工程和导入.c文件笔者已在文章(蓝桥杯单片机设计与开发_标准模板)中向大家详细介绍了,这里就不再赘述。
读者可下载赛点资源包(蓝桥杯单片机设计与开发_赛点资源数据包),解压后可得到以下图片所示文件。
在这里插入图片描述
我们双击打开文件“3-底层驱动代码参考”文件,将得到以下 .c.h 文件。接下来将 iic.ciic.h 文件拷贝到工程所在文件夹中,并在编译器中将这两个文件导入,便可以开始编写程序了。
![[Pasted image 20231020210509.png]]

2、AT24C02 存储函数封装==

首先,在编写驱动函数之前,我们需要在底层驱动代码 iic.c 文件中编写 存储读写函数。我们可以打开赛点资源数据包中的文件“5-竞赛板芯片资料”。

在这里插入图片描述

打开“AT24C02”芯片手册。笔者将借助芯片手册中的资料编写温度读取函数并为大家讲解。
![[Pasted image 20231020214703.png]]

向EEPROM写数据:编写存储写函数,传入存储地址和指向存储值的指针以及数据长度,具体每条代码的含义都已经注释,在这里将不再赘述。

// 向EEPROM写数据
void EEPROM_Write(unsigned char addr,unsigned char *p,unsigned char lens)     
{
	unsigned char i;
	
	IIC_Start();              //开启总线
	IIC_SendByte(0xa0);       //0xa0: 和地址为0xa0的芯片通信,即AT24C02
	IIC_WaitAck();            //等待应答
	IIC_SendByte(addr);       //输入数据要保存的地址
	IIC_WaitAck();            //等待应答
	for(i = 0;i<lens;i++)
	{
		IIC_SendByte(p[i]);       //输入保存的数据
	  IIC_WaitAck();            //等待应答
	}
	IIC_Stop();               //关闭总线
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

其中,在编写模数转换函数指令可通过查阅芯片资料手册,不需要死记硬背。

  • AT24C02芯片地址前四位默认为 1010a
  • 后四位 A2\A1\A0 视具体的接线而定,最低位为 0 则表示向芯片写数据,为 1 则表示从芯片读数据。
    ![[Pasted image 20231020215603.png]]

从EEPROM读数据:编写程序从存储模块中读函数。

// 从EEPROM读数据
void EEPROM_Read(unsigned char addr,unsigned char *p,unsigned char lens)     
{
	unsigned char i;
	
	IIC_Start();              //开启总线
	IIC_SendByte(0xa0);       //0xa0: 和AT24C02芯片通信
	IIC_WaitAck();            //等待应答
	IIC_SendByte(addr);       //写通信地址
	IIC_WaitAck();            //等待应答
	IIC_Stop();               //关闭总线
	
	IIC_Start();              //开启总线
	IIC_SendByte(0xa1);       //0xa1: 从AT24C02读数据
	IIC_WaitAck();            //等待应答
	for(i=0;i<lens;i++)
	{
		p[i] = IIC_RecByte();     //接受数据
		IIC_SendAck(0);           //发送应答:未读完数据
	}
	IIC_SendAck(1);           //发送非应答:已经读完数据
	IIC_Stop();               //关闭总线
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在编写完时间读写函数后务必要在 iic.h 文件中声明函数,才可在主函数中调用。

#ifndef _IIC_H
#define _IIC_H

void EEPROM_Read(unsigned char addr,unsigned char *p,unsigned char lens);
void EEPROM_Write(unsigned char addr,unsigned char *p,unsigned char lens);

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3、主函数调用

在主函数中调用时间模块底层函数,首先需要在主函数开头包含驱动 iic.h 头文件。

#include "STC15F2K60S2.h"
#include "iic.h"
  • 1
  • 2

main主函数
主程序调用比较简单,下文中实现了 采用AT24C02模块存储数组数据;并通过按键从存储模块中取出存储的数据进行显示。由于考虑初学者基础较为薄弱,因此将完整的 main.cpp 代码贴出来,包含中断函数、矩阵键盘、数码管显示等,并且在关键处进行了注释,希望对大家有所帮助。

// 包含头文件
#include "STC15F2K60S2.h"
#include "iic.h"

// 数据类型定义
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long int

// 8位数码管状态
u8 dspbuf[8] = {10,10,10,10,10,10,10,10};
u8 code tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x89,0xc1,0xbf};
	             //  0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7 ,  8 ,  9 , 灭 , 0. , 1. , 2. , 3. , 4. , 5. , 6. , 7. , 8. , 9. ,  H ,  U ,  -  ; 
	             //  0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7 ,  8 ,  9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23  ;
u8 dspcom = 0;
bit key_flag = 0,EEPROM_flag = 0;

// 定时器初始化
void Timer0Init(void)		//2毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x40;		//设置定时初值
	TH0 = 0xA2;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	ET0 = 1;		//开定时中断
	EA= 1;			//开总中断
}

// 573锁存器封装成函数
void door(u8 choose,u8 input)
{
	P2 = (P2 & 0x1f) | choose;
	P0 = input;
	P2 &= 0x1f;	
}

// 关数码管
void clo_num()
{
	dspbuf[0] = 10;
	dspbuf[1] = 10;
	dspbuf[2] = 10;
	dspbuf[3] = 10;
	dspbuf[4] = 10;
	dspbuf[5] = 10;
	dspbuf[6] = 10;
	dspbuf[7] = 10;
}

// 关灯、蜂鸣器、数码管
void all_init()	
{
 	door(0x80,0xff);
	door(0xa0,0xaf);
	clo_num();
}

// 数码管显示函数
void display()
{			  
	door(0xe0,0xff);		//消隐

	door(0xc0,0x01<<dspcom);
	door(0xe0,tab[dspbuf[dspcom++]]);
	
	if(dspcom >= 8)     //or dspcom &= 0x07;
		dspcom = 0;
}

// 矩阵键盘,接KBD
u8 keypress = 0,keyvalue = 0xff,keyread = 0;
u8 Read_key(void)		                              	
{
    u8 key_m,cal;
    
    P3 = 0xf0;P42=1;P44=1;
  	P36=P42;P37=P44;			   //变量替换
    key_m = (P3 & 0xf0);

    if(key_m != 0xf0) 
        keypress++;
   else
        keypress = 0; 
    
    if(keypress == 3)
    {
		  keypress = 0;
	  	keyread = 1;
		  switch(key_m)
        {
            case 0x70:cal = 0;break;                
            case 0xb0:cal = 1;break;    
            case 0xd0:cal = 2;break;    
            case 0xe0:cal = 3;break;
        }
        
        P3 = 0x0f;P42=0;P44=0;
				P36=P42;P37=P44;			   //变量替换
        key_m = (P3 & 0x0f);
        
			switch(key_m)
					{
							case 0x0e:keyvalue = (4*cal+7);break;                
							case 0x0d:keyvalue = (4*cal+6);break;    
							case 0x0b:keyvalue = (4*cal+5);break;    
							case 0x07:keyvalue = (4*cal+4);break;
					}
    }

    P3 = 0x0f;P42=0;P44=0;
		P36=P42;P37=P44;			                //变量替换
    key_m = (P3&0x0f);
	
    if((keyread == 1) && (key_m == 0x0f))
    {
        keyread = 0;
        return keyvalue;	
    }
    
    return 0xff;  
}

// float第N个字节转换成uint8
u8 Float2Uint8(float num,u8 N)
{
    u8* temp;
    temp = (u8 *)&num;
    return *(temp+N);
}

// float转换为uint32
u32 Float2Uint32(float dat)
{
    u32 temp = 0;
		u8 i;
    for(i=0;i<4;i++)
        temp |= Float2Uint8(dat,i)<<(i*8);
    return temp;
}

float Uint82Float(u8* p)
{
    float temp;
    *((u8*)&temp) = *p;
    *((u8*)&temp+1) = *(p+1);
    *((u8*)&temp+2) = *(p+2);
    *((u8*)&temp+3) = *(p+3);
    return temp;
}
//uint32转float
float Uint322Float(u32 dat)
{
    float temp;
    *((u8*)&temp) = dat&0x00ff;
    *((u8*)&temp+1) = (dat>>8)&0x00ff;
    *((u8*)&temp+2) = (dat>>16)&0x00ff;
    *((u8*)&temp+3) = (dat>>24)&0x00ff;

    return temp;
}

//````````````````````````````````主函数````````````````````````````````````
u8 num = 50;
void main()
{
	u8 key_re,date,EEPROM_w = 0;
	u8 str[8] = {0,1,3,1,4,5,2,0},lens = 4;
	u8 put[8] = {1,1,1,1,1,1,1,1};
	float dat = 12.345,dat_show;
	u8 input[4],ouput[4];
	u32 temp_test = 0,temp1,show;
	
	all_init();
	Timer0Init();
	
	// 向EEPROM中写入数据 地址为 1,数据长度为 8
	EEPROM_Write(1,str,8);

 	while(1)
	{
		
		if(key_flag)			
		{
			key_flag = 0;
			key_re = Read_key();
			
			if(key_re != 0xff)
			{
				switch(key_re)
				{
					case 7:EEPROM_Read(1,put,8);;break;	
					case 6: break;
					case 5:
							temp1 = dat*1000;
							*(u32 *)input = temp1;
							EEPROM_Write(0,input,4);
					break;
					case 4:
							EEPROM_Read(0,ouput,4);
							show = ouput[0]*256*256*256+ouput[1]*256*256+ouput[2]*256+ouput[3];
					break;
					case 10:door(0xa0,0xaf);break;
					case 11:door(0xa0,0xef);break;
					case 9:;break;
					case 8:;break;
					case 19:EEPROM_w = 1;break;	
					case 18:EEPROM_w = 0;
					        clo_num();break;
					case 17:dspbuf[6] = num%100/10;
				          dspbuf[7] = num%10;     break;
					case 16:door(0x80,0xdf);break;
					default:break;
				}
			}
		}
		
			dspbuf[0] = show/100000000;
			dspbuf[1] = show%10000000/1000000;
			dspbuf[2] = show%1000000/100000;
			dspbuf[3] = show%100000/10000;
			dspbuf[4] = show%10000/1000;
			dspbuf[5] = show%1000/100;
			dspbuf[6] = show%100/10;
			dspbuf[7] = show%10;
		
			if(EEPROM_flag)
			{
				EEPROM_flag =0;	
				dspbuf[0] = put[0];
				dspbuf[1] = put[1];
				dspbuf[2] = put[2];
				dspbuf[3] = put[3];
				dspbuf[4] = put[4];
				dspbuf[5] = put[5];
				dspbuf[6] = put[6];
				dspbuf[7] = put[7];
			}
	}
}

// 定时器0中断服务函数
void timer0() interrupt 1
{
	static u8  t_20ms = 0,t_50ms = 0;   //MAX = 500 ms

	display();		//数码管显示函数放里面

	t_20ms++;
	t_50ms++;

	if(t_20ms >= 10)	//每20ms扫描一次按键
	{
		t_20ms = 0;
		key_flag = 1;
	}		
	
	if(t_50ms >= 50)
	{
	  t_50ms = 0;
		EEPROM_flag = 1;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265

至此,本次 AT24C02 存储模块已介绍完毕。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/560774
推荐阅读
相关标签
  

闽ICP备14008679号