AT24C02介绍
I2C(Inter-Integrated Circuit)是一种串行通信总线协议,用于在集成电路之间进行通信。AT24C02是一种基于I2C总线的串行EEPROM(Electrically Erasable Programmable Read-Only Memory)存储器芯片。
AT24C02具有2K位(256字节)的容量,可以通过I2C总线与微控制器或其他设备进行通信。它可以存储数据,并且支持通过I2C总线进行读取和写入操作。AT24C02通常用于存储设备配置数据、校准值、日志数据等。
使用AT24C02芯片时,需要连接到微控制器或其他主设备的I2C总线上,并通过I2C协议进行读写操作。这种芯片在嵌入式系统和各种电子设备中广泛应用。
I^c时序结构 :这个很重要后面写程序需要参考
数据帧:数据的接收和回应
复合格式的数据帧
以上是相关理论知识准备:接下来使用程序对AT24C02进行程序实现
该程序使用到的c语言文件有Delay,LCD1602,AT24C02,I2C以及各自的头文件
#ifndef __DELAY_H_
#define __DELAY_H_
// 编写函数函数声明需要的代码
void Delay(unsigned int xms);
#endif
延时函数c语言文件
延时函数具体程序代码
// 实现函数的功能
void Delay(unsigned int xms){
unsigned char i ,j;
while(xms --){
i = 2;
j = 239;
do{
while(j --);
}while(-- i);
}
}
step2:LCD1602头文件以及程序实现代码
LCD1602头文件
LCD1602头文件具体代码
#ifndef __LCD1602_H__
#define __LCD1602_H__
//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
#endif
LCD1602c语言程序
#include
#include
#include
//引脚配置:
sbit LCD_RS=P3^5;
sbit LCD_RW=P3^6;
sbit LCD_EN=P3^4;
#define LCD_DataPort P0
//函数定义:
/**
* @brief LCD1602延时函数,12MHz调用可延时1ms
* @param 无
* @retval 无
*/
void LCD_Delay()
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/**
* @brief LCD1602写命令
* @param Command 要写入的命令
* @retval 无
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602写数据
* @param Data 要写入的数据
* @retval 无
*/
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
/**
* @brief LCD1602初始化函数
* @param 无
* @retval 无
*/
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01);//光标复位,清屏
}
/**
* @brief 在LCD1602指定位置上显示一个字符
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @param Char 要显示的字符
* @retval 无
*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
/**
* @brief 在LCD1602指定位置开始显示所给字符串
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串
* @retval 无
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriteData(String[i]);
}
}
/**
* @brief 返回值=X的Y次方
*/
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i0;i--)
{
LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD1602指定位置开始以有符号十进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:-32768~32767
* @param Length 要显示数字的长度,范围:1~5
* @retval 无
*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
unsigned char i;
unsigned int Number1;
LCD_SetCursor(Line,Column);
if(Number>=0)
{
LCD_WriteData('+');
Number1=Number;
}
else
{
LCD_WriteData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
}
}
/**
* @brief 在LCD1602指定位置开始以十六进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~0xFFFF
* @param Length 要显示数字的长度,范围:1~4
* @retval 无
*/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i,SingleNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingleNumber=Number/LCD_Pow(16,i-1)%16;
if(SingleNumber<10)
{
LCD_WriteData(SingleNumber+'0');
}
else
{
LCD_WriteData(SingleNumber-10+'A');
}
}
}
/**
* @brief 在LCD1602指定位置开始以二进制显示所给数字
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~1111 1111 1111 1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
}
}
独立键盘实现头文件以及代码key.h
#ifndef __KEY_H__
#define __KEY_H__
unsigned char Key();
#endif
独立键盘实现头文件以及代码key.c
#include
#include "Delay.h"
/**
* @brief 获取独立按键键码
* @param 无
* @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
*/
unsigned char Key()
{
unsigned char KeyNumber=0;
if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
return KeyNumber;
}
AT24C02程序头文件
#ifndef __AT24C02_H_
#define __AT24C02_H_
void AT24C02_WriteByte(unsigned char WordAddress,Data);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);
#endif
AT24C02程序实现文件
#include
#include "I2C.h"
#define AT24C02_ADDRESS 0xA0
/*
@brief AT24C02写入一个字节
@param WordAddress 要写入字节地址
@param Data 要写入的数据
@retval 没有返回值
*/
void AT24C02_WriteByte(unsigned char WordAddress,Data){
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_SendByte(Data);
I2C_ReceiveAck();
I2C_Stop();
}
/*
@brief AT24C02读取一个字节
@param WordAddress 要读出字节地址
@param Data 要读出的数据
@retval 读出的数据
*/
unsigned char AT24C02_ReadByte(unsigned char WordAddress){
unsigned char Data;
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_Start();
I2C_SendByte(AT24C02_ADDRESS|0x01);
I2C_ReceiveAck();
Data = I2C_ReceiveByte();
I2C_SendAck(1);
I2C_Stop();
return Data;
}
I2C头文件代码
#ifndef __I2C_H_
#define __I2C_H_
void I2C_Start(void);
void I2C_Stop(void);
void I2C_SendByte(unsigned char Byte);
unsigned char I2C_ReceiveByte(void);
void I2C_SendAck(unsigned char AckBit);
unsigned char I2C_ReceiveAck(void);
#endif
I2C程序实现代码
......
I2C的具体代码
#include
// 单片机引脚的位定义
sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;
void I2C_Start(void){
I2C_SDA = 1;
I2C_SCL = 1;
I2C_SDA = 0;
I2C_SCL = 0;
}
void I2C_Stop(void){
I2C_SDA = 0;
I2C_SCL = 1;
I2C_SDA = 1;
}
/*
@brief I2C 发送一个字节
@param Byte 要发送的字节
@retval 无 没有返回值
*/
void I2C_SendByte(unsigned char Byte){
unsigned char i;
// 一个字节是8位所以需要使用for循环循环8次,每次循环按位右移一次
for(i = 0; i< 8; i++){
I2C_SDA = Byte&0x80 >> i;//10000000
I2C_SCL = 1;
I2C_SCL = 0;
}
}
/*
@brief I2C 接收一个字节
@param 无
@retval 接收到一个字节的数据
*/
unsigned char I2C_ReceiveByte(void){
unsigned char Byte = 0x00,i;
I2C_SDA = 1;
for(i = 0; i < 8; i++){
I2C_SCL = 1;
if(I2C_SDA){
Byte |= (0X80>>i);//1000 0000
}
I2C_SCL = 0;
}
return Byte;
}
/*
@brief I2C 发送应答
@param AckBit 应答位0为应答1为不应答
@retval 无 没有返回值
*/
void I2C_SendAck(unsigned char AckBit){
I2C_SDA = AckBit;
I2C_SCL = 1;
I2C_SCL = 0;
}
/*
@brief I2C 接收应答
@param 没有参数
@retval 接收到的应答位
*/
unsigned char I2C_ReceiveAck(void){
unsigned char AckBit = 0;
I2C_SDA = 1;
I2C_SCL = 1;
if(I2C_SDA){
AckBit = 1 ;
}
I2C_SCL = 0;
return AckBit;
}
main函数文件测试程序是否能够正确的发送和接收数据
#include
#include "LCD1602.H"
#include "Delay.h"
#include "AT24C02.H"
unsigned char Data;
unsigned char KeyNum;
unsigned int Num;
int main(){
LCD_Init();
LCD_ShowNum(1,1,Num,5);
// // 第一位指定的是地址,第二位指定的是数据
// AT24C02_WriteByte(1,147);
// // 每次写完需要延迟一次,不然会报错
// Delay(5);
// Data = AT24C02_ReadByte(1);
// LCD_ShowNum(2,1,Data,3);
while(1){
KeyNum = Key();
if(KeyNum == 1){
Num++;
LCD_ShowNum(1,1,Num,5);
}
if(KeyNum == 2){
Num--;
LCD_ShowNum(1,1,Num,5);
}
if(KeyNum == 3){
AT24C02_WriteByte(0,Num%256);
Delay(5);
AT24C02_WriteByte(1,Num/256);
Delay(5);
LCD_ShowString(2,1,"Write Ok");
Delay(1000);
LCD_ShowString(2,1," ");
}
if(KeyNum == 4){
Num = AT24C02_ReadByte(0);
Num |= AT24C02_ReadByte(1)<<8;
LCD_ShowNum(1,1,Num,5);
LCD_ShowString(2,1,"Read Ok");
Delay(1000);
LCD_ShowString(2,1," ");
}
}
}