赞
踩
04 蓝桥杯单片机设计与开发_基础模块_PCF8591-CSDN博客,承接上文,本文将继续介绍剩余蓝桥杯涉及模块(AT24C02、PWM、串口通信、NE555以及超声波测距),为大家做出详细编程指导。
笔者将基于蓝桥杯官方给的赛点资源包(蓝桥杯单片机设计与开发_赛点资源数据包)进行编程,为大家讲解编程调用各语句的含义,帮助大家编写温度传感器的程序,也便于大家记忆。
首先,创建工程和导入.c文件笔者已在文章(蓝桥杯单片机设计与开发_标准模板)中向大家详细介绍了,这里就不再赘述。
读者可下载赛点资源包(蓝桥杯单片机设计与开发_赛点资源数据包),解压后可得到以下图片所示文件。
我们双击打开文件“3-底层驱动代码参考”文件,将得到以下 .c
和 .h
文件。接下来将 iic.c
和 iic.h
文件拷贝到工程所在文件夹中,并在编译器中将这两个文件导入,便可以开始编写程序了。
首先,在编写驱动函数之前,我们需要在底层驱动代码 iic.c
文件中编写 存储读写函数。我们可以打开赛点资源数据包中的文件“5-竞赛板芯片资料”。
打开“AT24C02”芯片手册。笔者将借助芯片手册中的资料编写温度读取函数并为大家讲解。
向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(); //关闭总线 }
其中,在编写模数转换函数指令可通过查阅芯片资料手册,不需要死记硬背。
1010
即 a
A2\A1\A0
视具体的接线而定,最低位为 0
则表示向芯片写数据,为 1
则表示从芯片读数据。从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(); //关闭总线 }
在编写完时间读写函数后务必要在 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
在主函数中调用时间模块底层函数,首先需要在主函数开头包含驱动 iic.h
头文件。
#include "STC15F2K60S2.h"
#include "iic.h"
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 *)# 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; } }
至此,本次 AT24C02 存储模块已介绍完毕。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。