IIC读写AT24C02代码2——串口命令控制多页读写
通过串口输入 R 、W 进行控制程序读写IIC设备。波特率9600bps,晶振115200HZ。
main.c
/*-----------------------------------------------
IIC编程 1
编写:Louis
邮箱:kaly.liu@163.com
日期:2015.06.01
改动:通过串口命令R/W,控制EEPROM的读R写W。并从串口提示。 改进:添加对页读写功能
晶振:11.0592MHZ
NOTE:*通过实測发现。AT24C02能够连续写入16BYTE字节。并且地址要连续的两个页。就是0~15,16~31,。。。
------------------------------------------------*/
#include <REG52.H> #include<string.h>
#include"uart.h"
#include "iic.h" sbit WP=P1^0;
sbit LED7=P1^7; unsigned char idata temp[8];
unsigned char rxnum;
unsigned char flag2;
unsigned char EEPROM_WR_FLAG=0; code const char str1[] = "The string is 来自单片机!\r\n";
code const char str2[] = "Author: louis \r\n"; //const 限定一个变量不同意被改变。在一定程度上提高程序安全性和可靠性
//code 存储区间为 程序存储区
/***************函数声明*******************/
void InitUART(void);
void SendOneByte(uint8);
void SendrStr(uint8 *ptr); void main(void)
{
unsigned char Control,*p1,*p2;
unsigned char buf1[]="The first page!!The second page!The third page!!"; /* 发送缓冲区 */
unsigned char idata buf2[49]; /* 接收缓冲区 */ unsigned char Length;
unsigned int addr ,i=0; /* 24Cxx片内地址 */
WP=0;
// P4SW|= 0x10;
LED7=1;
InitUART(); while(str2[i]!='\0')
{
SendOneByte(str2[i++]);
}
SendrStr(str1); ES =1;
EA =1; p1=buf1;
p2=buf2; addr=0; ////片内地址 AT24C02为0~255 , 32page*8byte = 256个字节/////
Length=48; ////// 读写长度 //////
enumer=AT2402; /// 读写AT24C02//// while(1){
if(EEPROM_WR_FLAG=='W'){
Control=0xae; /// 1010 1110 写操作///
RW24xx(p1,Length,addr,Control,enumer); // 写操作 //
for(i=0;i<10000;i++);
//要添加延时···才可正确的读取数据!
//在STOP和START之间有个 write cycle,一般有个最大值Twr.这是设备内部进行写入数据须要的时间,所以此处的延迟须要 大于这个 最大值Twr。
// Delay(1000);//1:6.18us; 2:8.36us 3:10.55us △=2.18us
EEPROM_WR_FLAG=0;
} if(EEPROM_WR_FLAG=='R'){
Control=0xaf; ///读操作///
RW24xx(p2,Length,addr,Control,enumer);// 读
EEPROM_WR_FLAG=0;
SendrStr(p2);
SendrStr("\r\n"); } }//while } /****************中断服务函数***************/
void UART_ISR(void) interrupt 4
{
uint8 RX_Data;
//仅仅响应"接收"中断,"发送"中断来了就直接抹掉
if(RI)
{
RI = 0; //串口中断标志不能自己清除。须要手动清除
RX_Data=SBUF;
EEPROM_WR_FLAG = RX_Data;
SendOneByte(EEPROM_WR_FLAG);
SendrStr(":\r\n");
}
else
TI = 0; //串口发中断是发送完缓冲区数据之后产生
}
uart.h头文件
/*----------------------------------------------- 编写:刘宗铭
邮箱:kaly.liu@163.com
日期:2015.05
修改:无 ------------------------------------------------*/ #include<reg52.h> //包括头文件。普通情况不须要修改。头文件包括特殊功能寄存器的定义 /*******************************************************************
请提前计算一下所选晶振能达到的最快速度,波特率不能超过最快速度
(1) 波特率加倍(SMOD=1): Max_Baud = FOSC/12/16
(2) 波特率不加倍(SMOD=0):Max_Baud = FOSC/12/32
比如:22.1184MHz晶振,波特率加倍时,最大波特率=22118400/12/16=115200
*******************************************************************/
#define FOSC 11059200 //振荡频率
#define BAUD 9600 //波特率
#define SMOD 1 //是否波特率加倍
#if SMOD
#define TC_VAL (256-FOSC/16/12/BAUD)
#else
#define TC_VAL (256-FOSC/32/12/BAUD)
#endif typedef unsigned char uint8;
typedef unsigned int uint16; /****************串口初始化函数*************/
void InitUART(void)
{
TMOD = 0x20; //定时器1,模式2工作模式
SCON = 0x50; //串口工作模式1。同意REN /* SCON: 模式 1, 8-bit UART, 使能接收 */
TH1 = TC_VAL;
TL1 = TH1;
PCON = 0x80; //发送速率加倍
ES = 1;
EA = 1;
TR1 = 1;
}
/**************串口发送字符函数*************/
void SendOneByte(uint8 c)
{
ES = 0; //禁止中断,让串口安心工作啊
SBUF = c;
while(!TI); //等待发送完成
TI = 0; //清TI中断
ES = 1; //打开中断
}
/**************串口发送字符串函数*************/ /**************串口发送字符串函数*************/
void SendrStr(const uint8 *ptr)
{ for(;*ptr!='\0';ptr++)
{
SendOneByte(*ptr);
}
}
IIC.h头文件
/*----------------------------------------------- 编写:<span style="font-family: Arial, Helvetica, sans-serif;">Louis </span> 邮箱:kaly.liu@163.com
日期:2015.05
改动:加入多页读写功能
器件的型号 我用的是AT24C02 32PAGE*8BYTE = 2Kbit
------------------------------------------------*/
#include <intrins.h>
#include<reg52.h> #define ERROR 10 //同意ERROR的最大次数 sbit SDA=P1^2;
sbit SCL=P1^1; enum eepromtype {AT2401,AT2402,AT2404,AT2408,AT2416,AT2432,AT2464,AT24128,AT24256};/*器件的型号 我用的是AT24C02*/
enum eepromtype enumer; //定义一个枚举变量 /* * * * * * * * 一个简单延时程序 * * * * * * * * * * * * */
void Delay(unsigned char DelayCount)
{ while(DelayCount--); //推断 + 运行 2个机器周期
}
/* * * * * 下面是对IIC总线的操作子程序 * * * * */
/* * * * * * 启动总线 * * * * */
void Start(void)
{ SCL=0; /* SCL处于高电平时,SDA从高电平转向低电平表示 */
SDA=1; /* 一个"開始"状态,该状态必须在其它命令之前运行 */
Delay(2);
SCL=1;
Delay(2);
SDA=0;
Delay(2);
SCL=0;
SDA=1;
Delay(2);
} /* * * * * 停止IIC总线 * * * * */
void Stop(void)
{ SCL=0; /*SCL处于高电平时,SDA从低电平转向高电平 */
SDA=0; /*表示一个"停止"状态,该状态终止全部通讯 */
Delay(2);
SCL=1;
Delay(2); /* 空操作 */
SDA=1;
Delay(2);
SCL=0;
Delay(1000);
} /* * * * * 检查应答位 * * * * */
bit RecAck(void)
{ SCL=0;
SDA=1;
Delay(20);
SCL=1;
Delay(2);
Delay(2);
CY=SDA; /* 由于返回值总是放在CY中的 */
SCL=0;
Delay(20);
return(CY);
} /* * * * *对IIC总线产生应答 * * * * */
void Ack(void)
{ SDA=0; /* EEPROM通过在收到每一个地址或数据之后, */
SCL=1; /* 置SDA低电平的方式确认表示收到读SDA口状态 */
Delay(2);
SCL=0;
Delay(2);
SDA=1;
} /* * * * * * * * * 不对IIC总线产生应答 * * * * */
void NoAck(void)
{ SDA=1;
SCL=1;
Delay(2);
SCL=0;
} /* * * * * * * * * 向IIC总线写数据 * * * * */
void Send(unsigned char sendbyte)
{ unsigned char data j=8;
for(;j>0;j--)
{ SCL=0;
sendbyte <<= 1; /* 使CY=sendbyte^7; */
SDA=CY; /* CY 进位标志位 */
Delay(2);
SCL=1;
Delay(20);
}
SCL=0;
Delay(2);
} /* * * * * * * * * 从IIC总线上读数据子程序 * * * * */
unsigned char Receive(void)
{ register receivebyte,i=8;
SCL=0;
while(i--)
{ SCL=1;
receivebyte = (receivebyte <<1 ) | SDA;
Delay(2);
SCL=0;
// receivebyte = (receivebyte <<1 ) | SDA; //不能放在这里啊,放这里接受数据出错··!! Delay(2);
}
return(receivebyte);
} /* ----- AT24C01~AT24C256 的读敲代码 ------ */
bit RW24xx(unsigned char *DataBuff,unsigned char Length,unsigned int Addr,
unsigned char Control,enum eepromtype enumer)
{ unsigned char data j,i=ERROR;
unsigned int k;
bit errorflag=1; /* 出错标志 */
while(i--)
{ Start(); /* 启动总线 */
Send(Control & 0xfe); /* 向IIC总线写数据,器件地址 */
if(RecAck()) continue; /* 如写不对结束本次循环 */
if(enumer > AT2416)
{ Send((unsigned char)(Addr >> 8));//把整型数据转换为字符型数据:弃高取低,仅仅取低8位.假设容量大于32K位,使用16位地址寻址,写入高八位地址
if(RecAck()) continue;
}
Send((unsigned char)Addr); /* 向IIC总线写数据 */
if(RecAck()) continue; /* 如写不对结束本次循环 */
if(!(Control & 0x01)) //推断是读器件还是写器件 假设是写 0 就进去运行
{ j=Length;
errorflag=0; /* 清错误特征位 */
while(j--)
{
//******************此段推断页***多页读写功能***********************//
if(Addr%16==0)
{
Stop();
for(k=0;k<10000;k++);
Start(); /*启动总线*/
Send(Control & 0xfe); /*发送器件地址*/
if(RecAck()) continue; /* 如写不对结束本次循环 */ if(enumer > AT2416)
{
Send((unsigned char)(Addr >> 8));//把整型数据转换为字符型数据:弃高取低。仅仅取低8位.
//假设容量大于32K位,使用16位地址寻址。写入高八位地址
if(RecAck()) continue; /* 如写不对结束本次循环 */
}
Send((unsigned char)Addr); /*发送器件子地址*/
if(RecAck()) continue; /* 如写不对结束本次循环 */
}
Addr++;
//********************此段推断页***多页读写功能**************************// /*发送数据*/
Send(*DataBuff++); /* 向IIC总线写数据 */
if(!RecAck()) continue; /* 如写正确结束本次循环 */
errorflag=1;
break;
}
if(errorflag==1) continue;
// SendOneByte('O');
break;
}
else
{ Start(); /* 启动总线 */
Send(Control); /* 向IIC总线写数据 */
if(RecAck()) continue;//器件没应答结束本次本层循环
while(--Length) /* 字节长为0结束 */
{ *DataBuff ++= Receive();
Ack(); /* 对IIC总线产生应答 */
}
*DataBuff=Receive(); /* 读最后一个字节 */
NoAck(); /* 不对IIC总线产生应答 */
errorflag=0;
break;
}
}
Stop(); /* 停止IIC总线 */
if(!(Control & 0x01))
{
Delay(255);
Delay(255);
Delay(255);
Delay(255);
}
return(errorflag);
}
IIC读写AT24C02代码2——串口命令控制多页读写的更多相关文章
- 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验二十:SDRAM模块③ — 页读写 α
实验二十:SDRAM模块③ — 页读写 α 完成单字读写与多字读写以后,接下来我们要实验页读写.丑话当前,实验二十的页读写只是实验性质的东西,其中不存在任何实用价值,笔者希望读者可以把它当成页读写的热 ...
- 第十六章 IIC协议详解+UART串口读写EEPROM
十六.IIC协议详解+Uart串口读写EEPROM 本文由杭电网友曾凯峰根据小梅哥FPGA IIC协议基本概念公开课内容整理并最终编写Verilog代码实现使用串口读写EEPROM的功能. 以下为原文 ...
- Qt小项目之串口助手控制LED
Qt小项目之串口助手控制LED 前言 最近刚学了一点Qt开发上位机,尝试着做个小软件练练手.查找了很多资料,做了一个简单的串口助手,可以实现串口基本发送和接收功能,支持中文显示,还可以控制STM32开 ...
- 小草手把手教你 LabVIEW 串口仪器控制——初识VISA串口
有些人,学习一样东西时候,喜欢现成的例子.很多人学习一门技术,都喜欢现成的例子开始,比如学单片机的啊,最开始都是修改的例子吧,学语言的也是.最开始都是模仿.这个年头看书上的理论知识太浪费时间了.所以啊 ...
- 【iCore4 双核心板_ARM】例程四:USART实验——通过命令控制LED
实验原理: 开发板上自带一片CH340芯片,完成本实验电脑需要安装CH340驱动, CH340的TXD连接STM32的GPIO(PXC7),CH340的RXD连接STM32的 GPIO(PC6),通过 ...
- 【iCore1S 双核心板_ARM】例程四:USART通信实验——通过命令控制LED
实验原理: 开发板上自带一片CH340芯片,完成本实验电脑需要安装CH340驱动, CH340的TXD连接STM32的GPIO(PB6),CH340的RXD连接STM32的 GPIO(PB7),通过串 ...
- svn查看代码作者的命令
svn blame **.java | grep ** svn查看代码作者的命令
- 【转】Git 代码行统计命令集
查看git上个人代码量 git log --author="username" --pretty=tformat: --numstat | awk '{ add += $1; su ...
- ThinkPHP5.0.21&5.1.* 代码执行和命令执行漏洞利用
ThinkPHP5.0.21&5.1.* 代码执行和命令执行漏洞利用 ThinkPHP5.0.21&5.1.* exploit code execution and command ...
随机推荐
- sublime text3中使用Emmet部分标签无法闭合
转载自:http://geek100.com/2490/ 不过很早就发现br,input, img在sublime text中是没有闭合标签 / 的. 我一般都是手动补上的, 今天突然想起这个问题, ...
- [xampp] phpmyadmin 设置登录密码
$ cd /opt/lampp/bin $ ./mysqladmin -u root password 'new_password' $ vim ../phpmyadmin/config.inc.ph ...
- centos6.5 python2.7.8 安装scrapy总是出错【解决】
pip install Scrapy 报错: UnicodeDecodeError: 'ascii' codec can't decode byte 0xb4 in position python s ...
- php中parse_url函数的源码及分析
前言 看师傅们的文章时发现,parse_url出现的次数较多,单纯parse_url解析漏洞的考题也有很多,在此研究一下源码(太菜了看不懂,待日后再补充Orz) 源码 PHPAPI php_url * ...
- luogu P1938找工就业
一头牛在一个城市最多只能赚D元,然后它必须到另一个城市工作.当然它可以在别处工作一阵子后,又回到原来的城市再最多赚D美元.而且这样的往返次数没有限制城市间有P条单向路径,共有C座城市,编号1~C,奶牛 ...
- 6、Flask实战第6天:视图函数Response返回值
视图函数的返回值会被自动转换为一个响应对象,Flask的转换逻辑如下: 如果返回的是一个合法的响应对象,则直接返回 可以使用make_response函数来创建Response对象,这个方法可以设置额 ...
- 【DFS】Codeforces Round #398 (Div. 2) C. Garland
设sum是所有灯泡的亮度之和 有两种情况: 一种是存在结点U和V,U是V的祖先,并且U的子树权值和为sum/3*2,且U不是根,且V的子树权值和为sum/3. 另一种是存在结点U和V,他们之间没有祖先 ...
- 【分块】【哈希】bzoj3578 GTY的人类基因组计划2
每个房间用一个集合来维护,具体来说,就是给1-n的数每个数一个long long的hash值,往集合S里insert(i),就是S^=HASH[i]:erase(i),也是S^=HASH[i]. 用m ...
- 选择改变事件OnCheckedChange
1.效果图:选择正确的提示选对,选择错误提示选错 2.activity_main.xml <?xml version="1.0" encoding="utf-8&q ...
- 动态RIP配置路由表
动态RIP配置路由表 以Router11为例子: (1)配置端口ip(两个端口需要设置两个ip) Router(config)#inter f0/0 Router(config-if)#ip add ...