基于mini2440的IIC读写(裸机)
mini2440开发板提供的测试代码过于复杂,让人很难理解,而且有些错误,如GPE14-15不能设置上拉电阻,可是代码里却设置了,虽然无关紧要。为了方便学习,我在闲暇之时我研究了一下。IIC的原理是比较简单的,可是在实际编程中却遇到很多困难。不知道哪里出了错误,有些逻辑上认为正确的,但在硬件上却不能实现。如下两行代码:
rGPECON &= ~(0x0f<<28);
rGPECON |= (0xa0<<28);
是为设置GPE14、GPE15位SCL和SDA的,在加上第一句代码后烧写程序就运行失败了。现在还不知道为什么加上第一行代码后就失败了,求高手解释。有些问题不实践真的不知道什么原因,所谓实践出真知嘛。希望对有兴趣的朋友有所帮助。
我们来看程序编写过程:
s3c2440的IIC七位地址时的数据接收和发送格式:
灰色的是从设备发送的。
IIC的具体时序:
由此可知SCL为高位时SDA从高位跃迁到低位时表示开始、SCL为高位时SDA从低位跃迁到高位时表示结束。我们可以设置IICSTAT寄存器来发送开始或结束信号。在第九个时钟时主设备或从设备拉低SDA,表示应答ACK。应答后产出中断,此时可以将数据写入IICDS或读出,然后清除中断标志位IICCON[4]恢复操作。具体的操作参考芯片手册或源代码。
mini2440的IIC接口连接一个EEPROM即AT24C08A,我选择页写和连续读来测试IIC接口。具体时序如下:
其中页写的时许很明确。但是连读读的时序前面不太明确,在数据手册中我们可以得知连续读是当前地址读和随机读的一种,所以前面的时序我采取随机读时许,即组合起来。要是还不太清楚请看源代码。随机读时序如下:
AT24C08A接法在硬件电路图中可知如下:
查数据手册可以其地址为0xa0或0xa1。最低位为读写标志。在s3c2440中根据IIC模式自动选择,所以地址我们只需填写0xa0即可。
值得注意的是EEPROM读写速度不是很快,所以每次读写一个字节都要加一定延时,这点十分关键。这往往是程序读写失败的原因。当然我们也需要设置好SCL的频率。在IICCON里设置这里不多说。
在接收模式下最后一个字节数据不发送ACK这点也需要注意。
测试代码中我们采用将数据写入EEPROM中然后读取出来输出到串口来检验,程序可以采用中断或轮询,代码如下:
mian.c部分
#define GLOBAL_CLK 1 #include "def.h"
#include "option.h"
#include "2440addr.h"
#include "profile.h"
#include "mmu.h" typedef unsigned char uchar;
typedef unsigned int uint; extern void AT24C08_wirte(uchar waddr, uchar *dat, int num);
extern void AT24C08_read(uchar waddr, uchar *rev, int num);
extern void IIC_init(void);
extern void delay(int time); uchar dat[]={"0123456789abcdef"};
uchar rev[50]={0}; void Main(void)
{ rGPBCON=(1<<0);//关闭蜂鸣器
rGPBDAT=0x00; IIC_init(); AT24C08_wirte(0x00, dat, 16);
Uart_Printf("\n\n");
AT24C08_read(0x00, rev, 10); Uart_Printf("\n%s\n",rev);
}
IIC.c部分
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "profile.h"
#include "mmu.h" typedef unsigned char uchar;
typedef unsigned int uint;
void __irq IIC_INT(void); int flag=1;//中断标志 void delay(int time)
{
int i,j,k;
for(i=0;i<100;++i)
for(k=0;k<100;++k)
for(j=0;j<time;j++);
} //IIC初始化
void IIC_init(void)
{
//设置GPE15、GPE14为SDA、SCL
rGPECON |= (0xa0<<28); //允许ACK、允许中断、发送频率Khz
rINTMSK &= ~(1<<27);
rIICCON |= (1<<7 | 0<<6 | 1<<5 | 0xf);
rIICSTAT |= 1<<4;//IICDS可写 MMU_Init();//映射地址
pISR_IIC = (unsigned)IIC_INT;//中断入口
} //AT24C08页写
void AT24C08_wirte(uchar waddr, uchar *dat, int num)
{
int i=0; rIICDS = 0xa0;//AT24C08地址
rIICSTAT =0xf0;//发送模式、发送开始信号
while(flag == 1)
delay(100);//等待中断
flag = 1; rIICDS = waddr;//起始地址
rIICCON = 0xaf;//清除中断标志位
while(flag == 1)
delay(100);//等待中断
flag = 1; for(i=0;i<num;++i){
rIICDS = *(dat + i);
rIICCON = 0xaf;//清除中断标志位
while(flag == 1)
delay(100);//等待中断
flag = 1;
} rIICSTAT =0xd0;//发送停止位
rIICCON = 0xaf;//清除中断标志位
delay(100);
} //AT24C08连续读
void AT24C08_read(uchar waddr, uchar *rev, int num)
{
int i=0; rIICDS = 0xa0;
rIICSTAT =0xf0;//发送从机地址
while(flag == 1)
delay(100);//等待中断
flag = 1; rIICDS = waddr;//初始地址
rIICCON = 0xaf;//清除中断标志位
while(flag == 1)
delay(100);//等待中断
flag = 1; rIICDS = 0xa0;
rIICSTAT =0xb0;//接收模式
rIICCON = 0xaf;//清除中断标志位
while(flag == 1)
delay(100);//等待中断
flag = 1; for(i=0;i<num;++i){
if(i == (num-1)) rIICCON = 0x2f;
else rIICCON = 0xaf;
while(flag == 1)
delay(100);//等待中断
flag = 1;
*(rev + i) = rIICDS;
delay(100);
} rIICSTAT =0x90;//发送停止位
rIICCON = 0xaf;//清除中断标志位
delay(100);
} //中断服务函数
void __irq IIC_INT(void)
{
flag = 0;
rSRCPND |= 1<<27;//先清除SRCPND
rINTPND |= 1<<27;
} /*
#include "2440addr.h" typedef unsigned char uchar;
typedef unsigned int uint; void delay(int time)
{
int i,j,k;
for(i=0;i<100;++i)
for(k=0;k<100;++k)
for(j=0;j<time;j++);
} //IIC初始化
void IIC_init(void)
{
//设置GPE15、GPE14为SDA、SCL
rGPECON |= (0xa0<<28);
//允许ACK、允许中断、发送频率Khz
rIICCON |= (1<<7 | 0<<6 | 1<<5 | 0xf);
rIICSTAT |= (1<<4);//IICDS可写
} //AT24C08页写
void AT24C08_wirte(uchar waddr, uchar *dat, int num)
{
int i=0; rIICDS = 0xa0;//AT24C08地址
rIICSTAT =0xf0;//发送模式、发送开始信号
while(!(rIICCON & 0x10))
delay(100);//等待中断 rIICDS = waddr;//起始地址
rIICCON &= ~(1<<4);//清除中断标志位
while(!(rIICCON & 0x10))
delay(100);//等待中断 for(i=0;i<num;++i){
rIICDS = *(dat + i);
rIICCON &= ~(1<<4);//清除中断标志位
while(!(rIICCON & 0x10))
delay(100);//等待中断
} rIICSTAT =0xd0;//发送停止位
rIICCON &= ~(1<<4);//清除中断标志位
delay(100);
} //AT24C08连续读
void AT24C08_read(uchar waddr, uchar *rev, int num)
{
int i=0; rIICDS = 0xa0;
rIICSTAT =0xf0;//发送EEPROM地址
while(!(rIICCON & 0x10))
delay(100);//等待中断 rIICDS = waddr;//初始地址
rIICCON &= ~(1<<4);//清除中断标志位
while(!(rIICCON & 0x10))
delay(100);//等待中断 rIICDS = 0xa0;
rIICSTAT =0xb0;//接收模式
rIICCON &= ~(1<<4);//清除中断标志位
while(!(rIICCON & 0x10))
delay(100);//等待中断 for(i=0;i<num;++i){
if(i == (num-1)) rIICCON &= ~(1<<7 | 1<<4);//不发送ACK
else rIICCON &= ~(1<<4);//清除中断标志位
while(!(rIICCON & 0x10))
delay(100);//等待中断
*(rev+i) = rIICDS;
delay(100);
} rIICSTAT =0x90;//发送停止位
rIICCON &= ~(1<<4);//清除中断标志位
delay(100);
}
*/
这里包含了中断和轮询方式,其中轮询方式被我注释了。
我们通过代码在结合芯片手册可以直观的了解IIC接口的读写。代码中有很多注释方便大家阅读。
程序运行结果:
将0123456789abcdef写入EEPROM,然后读出0123456789。
源代码地址:http://download.csdn.net/detail/a16839678/6010041
基于mini2440的IIC读写(裸机)的更多相关文章
- 基于51单片机IIC通信的PCF8591学习笔记
引言 PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入.一个输出和一个串行I2C 总线接口.3 个地址引脚A0.A1 和A2 用于编程硬件地址,允许将最多8 个器件连接 ...
- 最简单的基于FFmpeg的内存读写的例子:内存转码器
===================================================== 最简单的基于FFmpeg的内存读写的例子系列文章列表: 最简单的基于FFmpeg的内存读写的 ...
- 最简单的基于FFmpeg的内存读写的例子:内存播放器
===================================================== 最简单的基于FFmpeg的内存读写的例子系列文章列表: 最简单的基于FFmpeg的内存读写的 ...
- (转)最简单的基于FFmpeg的内存读写的例子:内存播放器
ffmpeg内存播放解码 目录(?)[+] ===================================================== 最简单的基于FFmpeg的内存读写的例子系列文章 ...
- 基于mini2440的看门狗(裸机)
在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生 ...
- 基于51单片机IIC通信的AT24C02学习笔记
引言 最近在学习几种串行通信协议,感觉收获很多,这篇文章是学习IIC总线协议的第一篇文章,以后还会再写一篇关于PCF8591 IIC通信的ADDA转换芯片的文章. 关于IIC总线 IIC 即Inter ...
- 基于STM8的IIC协议---STM8-第五章
1. 综述 I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备. 它是由数据线SDA和时钟SCL构成的串行总线,可 ...
- 基于MGR+Atlas的读写分离尝试,以及MGR+Keepalived+Atlas自动故障转移+读写分离设想
目的是尝试altas的读写分离,现有一套搭建好做测试的MGR(单主),于是就腿搓绳,在MGR基础上搭建altas. 复制环境准备 读写分离理论上讲,跟复制模式没有关系,atlas负责的是重定向读写,至 ...
- 基于FPGA的I2C读写EEPROM
I2C在芯片的配置中应用还是很多的,比如摄像头.VGA转HDMI转换芯片,之前博主分享过一篇I2C协议的基础学习IIC协议学习笔记,这篇就使用Verilog来实现EEPROM的读写,进行一个简单的I2 ...
随机推荐
- js执行环境相关
Js执行过程 如果一个文档中存在多个代码段 步骤一:读入第一个代码段(js引擎并非一行一行执行,而是一段一段分析执行) 步骤二:做词法分析和语法分析,有错则报语法错误(比如括号不匹配等),并跳转到步骤 ...
- 简单的web三层架构系统【第三版】
今天是第三版,和前几天一样今天还是要对代码进行优化,三层架构是一种思想,具体能不能使得整个系统安全和高性能,还是要看代码编写的是否合理,逻辑性是否严谨. 昨天偶然间看到别人写的三层架构中,竟然没有在方 ...
- MySQL 开放局域网
局域网连接mysql报错: ERROR 1130: Host '192.168.0.220' is not allowed to connect to this MySQL server 解决方法: ...
- codeforces 609F. Frogs and mosquitoes 二分+线段树
题目链接 F. Frogs and mosquitoes time limit per test 2 seconds memory limit per test 512 megabytes input ...
- python自学笔记(二)python基本数据类型之字符串处理
一.数据类型的组成分3部分:身份.类型.值 身份:id方法来看它的唯一标识符,内存地址靠这个查看 类型:type方法查看 值:数据项 二.常用基本数据类型 int 整型 boolean 布尔型 str ...
- oracle如何修改字段类型(oracle总体知识2)
在一次做开发的时候,遇到需要将数据表的字段类型由number改成varchar,可是该字段又有值, 用 alter table t-name modify cname newType;会报错. 话说 ...
- perl5 第十三章 Perl的面向对象编程
第十三章 Perl的面向对象编程 by flamephoenix 一.模块简介二.Perl中的类三.创建类四.构造函数 实例变量 五.方法六.方法的输出七.方法的调用八.重载九.析构函数十.继承十一. ...
- JAVA GUI学习 - JList列表、JScrollPane滚动条组件学习
/** * 本例结合JList和JScrollPane共同使用 * @author Wfei * */ public class JListKnow extends JFrame { JList jL ...
- PHP第一章学习——了解PHP(上)
计划开启PHP学习教程,情况如下: 1.采用教程35章48个视频文件 2.时间4月29日-5月6日 共计8天 3.具体划分每天学习章节数不少于5个,预留5-6号时间为五一假期出玩情况 4.要求认真学习 ...
- SVNserver的本地搭建和使用
Subversion是优秀的版本号控制工具,其具体的的长处和具体介绍,这里就不再多说. 首先来下载和搭建SVNserver. 如今Subversion已经迁移到apache站点上了,下载地址: htt ...