mini2440裸机之I2C
// File Name : IIC.c
// Function : S3C2440 IIC-bus Master Tx/Rx mode Test Program
// (Interrupt / Non Interrupt (Polling))
// Program : Shin, On Pil (SOP)
// Date : May 21, 2002
// Version : 0.0
// History
// 0.0 : Programming start (March 11, 2002) -> SOP
//====================================================================
//串口会用到
#include "2440addr.h"
//寄存器宏定义
#include "2440lib.h"
//要用到的函数,函数的声明
#include "def.h"
//几个变量类型的宏定义
#include "IIC.h"
//volatile影响编译器编译的结果,指出volatile变量是随时可能
//发生变化的,与volatile变量有关的运算,不要进行编译优化
//定义一个数组,里面有256个数据
static volatile int _iicDataCount;
//IIC数据计数
static volatile int _iicStatus;
//IIC的状态
static volatile int _iicMode;
//IIC的模式
static int _iicPt;
//IIC的指针
// SMDK2440 IIC configuration
// GPE15=IICSDA, GPE14=IICSCL
// "Interrupt mode" for IIC block中断模式下的IIC操作
//===================================================================
void Test_Iic(void)
{
unsigned int i,j,save_E,save_PE;
static U8 data[256];
//定义一个256个8位数据的数组
//保护现场
save_PE = rGPEUP;
rGPEUP |= 0xc000;
//1100 0000 0000 0000禁止GPE14,GPE15上拉电阻
//GPE15:IICSDA , GPE14:IICSCL (应该为0xa0000000)???
//函数赋给向量地址
rINTMSK &= ~(BIT_IIC);
//使能IIC中断
//Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
// If PCLK 50.7MHz, IICCLK=PCLK/16=3.17MHz, Tx Clock(发送时钟)=IICCLK/16=0.198MHz
rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);
//2440 slave address=[7:1]=0x10 从机地址
rIICSTAT = 0x10;
//IIC bus data output enable(Rx/Tx) IIC数据输出使能
rIICLC = (1<<2)|(1);
//Filter enable, 5 clocks SDA output delay added by junon(感觉没用)
Uart_Printf("Write test data into AT24C02\n");
Wr24C080(0xa0,(U8)i,i);
//从设备的地址为0xa0,从从设备的内部0地址开始到256地址结束,写入0~256
for(i=0;i<256;i++)
data[i] = 0;
//data数组的元素全部初始化为0
for(i=0;i<256;i++)
Rd24C080(0xa0,(U8)i,&(data[i]));
//读取从设备的中的数据存入data数组中
//Line changed 0 ~ f
for(i=0;i<16;i++)
{
for(j=0;j<16;j++)
Uart_Printf("%2x",data[i*16+j]);
//打印刚才读出来的数据,即data数组里的值
Uart_Printf("\n");
//每16字节换一行
}
rINTMSK |= BIT_IIC;
//IIC操作结束,禁止IIC中断
rGPEUP = save_PE;
//恢复现场
rGPECON = save_E;
}
//*************************[ Wr24C080 ]****************************
// 函数名 从机地址 内部地址 写入的数据
//****************************************************************
void Wr24C080(U32 slvAddr,U32 addr,U8 data)
{
//过程就是:S(开始信号)---发送设备地址----设备内部地址----写入的数据
//设置为写数据模式
_iicPt = 0;
//IIC指针指向0地址
_iicData[0] = (U8)addr;
//给Data数组的0元素赋值,内部地址
_iicData[1] = data;
//给Data数组的1元素赋值,写入的数据
_iicDataCount = 2;
//数据计数初始值为2
rIICDS = slvAddr;
//0xa0 把从机设备地址给IICDS
rIICSTAT = 0xf0;
//MasTx,Start 设置为主发送模式,写IIC产生开始信号,使能RX/TX
//Clearing the pending bit isn't needed because the pending bit has been cleared.
//开始IIC写,发送完从机设备地址后,产生中断,进入中断函数
while(_iicDataCount!=-1
);//因为count是2,条件不成立然后等待!!第一次中断处理完后,count=1,然后再判断while中的条件不成立,继续等待,等到发送从机字设备的内部地址完后,产生中断有进入中断函数
//以下的while语句是判断接没接收到ACK信号
_iicMode = POLLACK;
//等待ACK应答模式,有应答表示从设备已经收到
{
rIICDS = slvAddr;
//slvAddr=0xa0
_iicStatus = 0x100;
//IICSTAT clear??
rIICSTAT = 0xf0;
//MasTx,Start,主发送模式,产生开始信号,使能串行输出,启动IIC
rIICCON = 0xaf;
//Resumes IIC operation.
while(_iicStatus==0x100);
//Wait until IICSTAT change
if(!(_iicStatus&0x1))
//判断IICSTAT第0位是不是0,是0的话表示接收到ACK了
break;
//When ACK is received
}
rIICSTAT=0xd0;
//产生停止信号,停止IIC
rIICCON=0xaf;
//重新配置IICCON.
Delay(1);
//等待直到IICSTAT的停止信号有效
//Write is completed.
}
//**********************[ Rd24C080 ] ***********************************
//读随机地址的数据读函数
//过程:S---发送设备地址---设备内部地址---发送设备地址---读取数据---NOACK---中止
void Rd24C080(U32 slvAddr,U32 addr,U8 *data)
{
_iicMode = SETRDADDR;
//设置读地址
_iicPt = 0;
_iicData[0] = (U8)addr;
_iicDataCount = 1;
//slvAddr=0xa0首先写入从设备地址
rIICSTAT = 0xf0;
//MasTx,Start开始启动信号
//Clearing the pending bit isn't needed because the pending bit has been cleared.
while(_iicDataCount!=-1);
//因为count是1,条件不成立然后等待!!第一次中断处理完后,count=0,然后再判断while中的条件不成立,继续等待,等到发送从机字设备的内部地址完后,产生中断有进入中断函数,执行完中断函数后,此时count=-1了所以就退出此while循环
_iicMode = RDDATA;
//读数据模式
_iicPt = 0;
_iicDataCount = 1;
//读一个数据(地址)
rIICDS = slvAddr;
//slvAddr=0xa0,又发送一次从机设备地址
rIICSTAT = 0xb0;
//1011,10~MasRx,1~Start,1~RxTx enable主接收模式
rIICCON = 0xaf;
//Resumes IIC operation.
while(_iicDataCount!=-1);
//等待,发送完设备地址后,产生中断进入中断函数执行第二次中断处理后,count=-1了,条件不成立退出while,继续下面的语句
//把从IICDS中接收到的数据送给指针data,
}
//-------------------------------------------------------------------------
void __irq IicInt(void)
//IIC中断初始化函数
{
U32 iicSt,i;
rSRCPND = BIT_IIC;
//Clear pending bit以便下次产生中断可以执行
rINTPND = BIT_IIC;
//Clear pending bit以便下次产生中断可以执行
iicSt = rIICSTAT;
//把IICSTAT状态寄存器的值赋给iicSt
if(iicSt & 0x8){}
//When bus arbitration is failed.当总线仲裁失败时,执行空操作
if(iicSt & 0x4){}
//When a slave address is matched with.当接收到的从地址和IICADD中地址匹配时,执行空操作
if(iicSt & 0x2){}
//When a slave address is 0000000b.接收到从地址为
0000000b
if(iicSt & 0x1){}
//When ACK isn't received未收到ACK应答信号执行空操作
//根据模式的不同执行不同的操作
{
case POLLACK:
//ACK模式
_iicStatus = iicSt;
//让_iicStatus就等于IICSTAT的值
break;
//读数据模式
if((_iicDataCount--)==0)
//count初始为1,不执行if代码段。完后count=0。第二次中断过来,条件成立就执行if内部代码
{
_iicData[_iicPt++] = rIICDS;
//重新把IICDS中的值读取出来到_iicData[1]
rIICSTAT = 0x90;
//Stop MasRx condition 1001 0000 产生停止信号
rIICCON = 0xaf;
//Resumes IIC operation.恢复IIC操作
Delay(1);
//Wait until stop condtion is in effect.
//Too long time... 等待直到停止信号起效
//The pending bit will not be set after issuing stop condition.
break;
//跳回到读函数中
}
//未读完最后一个字节不能产生ACK。读取IICDS中的数据
_iicData[_iicPt++] = rIICDS;
//The last data has to be read with no ack.
rIICCON = 0x2f;
//因为条件成立所以执行rIICCON=0x2f;主机产生NOACK,释放IIC操作
else
rIICCON = 0xaf;
//产生ACK,释放IIC操作
break;
//写数据模式
if((_iicDataCount--)==0)
//判断自减后是否为0.(2自减后为1,不为0)
{
rIICSTAT = 0xd0;
//Stop MasTx condition产生停止信号
rIICCON = 0xaf;
//Resumes IIC operation.恢复IIC的操作
Delay(1);
//Wait until stop condtion is in effect.等待直到停止信号起效
//The pending
bit will not be set after issuing stop condition.
break;
}
//自减后不为0,则执行下面的语句
rIICDS = _iicData[_iicPt++];
//_iicPt++是先判断,后自加,所以此条语句是rIICDS = _iicData[0],因为写函数中_iicData[0]=addr,
//即往从设备的addr地址发送数据
for(i=0;i<10;i++);
//在IICSCL上升沿之前有一个建立时间
rIICCON = 0xaf;
//恢复IIC的操作
break;
//SETRDADDR模式下的中断:
/*第一次中断处理后:count=0,_iicData[0]=IICDS中的值(又一次发送从设备地址引起的)*/
/*第二次中断处理后:count=-1,_iicPt=1(接收IICDS的值完毕后产生的中断*/
case SETRDADDR:
//设置读地址
// Uart_Printf("[ S%d ]",_iicDataCount);
//判断自减后是否为0
break;
//IIC operation is stopped because of IICCON[4]
rIICDS = _iicData[_iicPt++];
for(i=0;i<10;i++);
//For setup time until rising edge of IICSCL
rIICCON = 0xaf;
//Resumes IIC operation.
break;
//SETRDADDR模式下的中断:
/*第一次中断后:count=0,iicPt=1(发送从设备地址引起的)*/
/*第二次中断后:count=-1,iicPt=1因为if内部代码是直接跳回读函数,没继续执行if外面的代码,所以iicPt=1(发送从设备内部地址引起的)
default:
break;
}
}
// GPE15=IICSDA, GPE14=IICSCL
// "Non-Interrupt" mode for IIC block
//===================================================================
void Test_Iic2(void)
{
unsigned int i,j,save_E,save_PE;
static U8 data[256];
Uart_Printf("[ IIC Test(Polling) using KS24C080 ]\n");
save_PE = rGPEUP;
//Pull-up disable
rGPECON |= 0xa00000;
//GPE15:IICSDA , GPE14:IICSCL(应改为0xa0000000)
//Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
rIICCON = (1<<7) | (0<<6) | (1<<5) | (0xf);
//2440 slave address = [7:1]
rIICSTAT = 0x10;
//IIC bus data output enable(Rx/Tx)
//rIICLC = (1<<2)|(3); // Filter enable, 15 clocks SDA output delay added by junon
Uart_Printf("Write test data into KS24C080\n");
_Wr24C080(0xa0,(U8)i,255-i);
for(i=0;i<256;i++)
data[i] = 0;
for(i=0;i<256;i++)
_Rd24C080(0xa0,(U8)i,&(data[i]));
{
for(j=0;j<16;j++)
Uart_Printf("%2x ",data[i*16+j]);
Uart_Printf("\n");
}
rGPEUP = save_PE;
rGPECON = save_E;
}
void _Wr24C080(U32 slvAddr,U32 addr,U8 data)
{
_iicMode = WRDATA;
//设置为写数据模式
_iicPt = 0;
//IIC指针指向0地址
_iicData[0] = (U8)addr;
//给Data数组的0元素赋值,内部地址
_iicData[1] = data;
//给Data数组的1元素赋值,写入的数据
_iicDataCount = 2;
//数据计数初始值为2
rIICDS = slvAddr;
//0xa0 把从机设备地址给IICDS
//Master Tx mode, Start(Write), IIC-bus data output enable设置为主发送模式,写IIC产生开始信号,使能RX/TX
//Bus arbitration sucessful, Address as slave status flag Cleared,
//Address zero status flag cleared, Last received bit is 0
rIICSTAT = 0xf0;
//Clearing the pending bit isn't needed because the pending bit has been cleared.
while(_iicDataCount!=-1)
Run_IicPoll();
{
rIICDS = slvAddr;
_iicStatus = 0x100;
//To check if _iicStatus is changed
rIICSTAT = 0xf0;
//Master Tx, Start, Output Enable, Sucessful, Cleared, Cleared, 0
rIICCON = 0xaf;
//Resumes IIC operation.
while(_iicStatus==0x100)
Run_IicPoll();
if(!(_iicStatus & 0x1))
break;
//When ACK is received
}
rIICSTAT = 0xd0;
//Master Tx condition, Stop(Write), Output Enable
rIICCON = 0xaf;
//Resumes IIC operation.
Delay(1);
//Wait until stop condtion is in effect.
//Write is completed.
}
//************************[ _Rd24C080 ]********************************
void _Rd24C080(U32 slvAddr,U32 addr,U8 *data)
{
_iicMode = SETRDADDR;
_iicPt = 0;
_iicData[0] = (U8)addr;
_iicDataCount = 1;
rIICSTAT = 0xf0;
//MasTx,Start
//Clearing the pending bit isn't needed because the pending bit has been cleared.
while(_iicDataCount!=-1)
Run_IicPoll();
_iicPt = 0;
_iicDataCount = 1;
rIICDS = slvAddr;
rIICSTAT = 0xb0;
//Master Rx,Start
rIICCON = 0xaf;
//Resumes IIC operation.
while(_iicDataCount!=-1)
Run_IicPoll();
}
//该函数的作用就是判断一个字节是否发送或者接收完毕,因为已经说明了,只要传
//********************************************************************//
void Run_IicPoll(void)
{
if(rIICCON & 0x10)
}
//**********************[IicPoll ]**************************************
//该函数的主体是一个 switch 语句,用来判断现在进行的是什么操作,并进行
//***********************************************************************//
{
U32 iicSt,i;
iicSt = rIICSTAT;
if(iicSt & 0x8){}
//When bus arbitration is failed.
if(iicSt & 0x4){}
//When a slave address is matched with IICADD
if(iicSt & 0x2){}
//When a slave address is 0000000b
if(iicSt & 0x1){}
//When ACK isn't received
{
case POLLACK:
_iicStatus = iicSt;
break;
if((_iicDataCount--)==0)
{
_iicData[_iicPt++] = rIICDS;
rIICSTAT = 0x90;
//Stop MasRx condition
rIICCON = 0xaf;
//Resumes IIC operation.
Delay(1);
//Wait until stop condtion is in effect.
//Too long time...
//The pending bit will not be set after issuing stop condition.
break;
}
_iicData[_iicPt++] = rIICDS;
//The last data has to be read with no ack.
if((_iicDataCount)==0)
rIICCON = 0x2f;
//Resumes IIC operation with NOACK.
else
rIICCON = 0xaf;
//Resumes IIC operation with ACK
break;
if((_iicDataCount--)==0)
{
rIICSTAT = 0xd0;
//stop MasTx condition
rIICCON = 0xaf;
//resumes IIC operation
Delay(1);
//wait until stop condtion is in effect.
//The pending bit will not be set after issuing stop condition.
break;
}
rIICDS = _iicData[_iicPt++];
//_iicData[0] has dummy.
for(i=0;i<10;i++);
//for setup time until rising edge of IICSCL
rIICCON = 0xaf;
//resumes IIC operation.
break;
// Uart_Printf("[S%d]",_iicDataCount);
if((_iicDataCount--)==0)
{
break;
//IIC operation is stopped because of IICCON[4]
}
rIICDS = _iicData[_iicPt++];
for(i=0;i<10;i++);
//for setup time until rising edge of IICSCL
rIICCON = 0xaf;
//resumes IIC operation.
break;
break;
}
}
mini2440裸机之I2C的更多相关文章
- mini2440裸机音乐播放器(非常久曾经的笔记)
[这是好久曾经写的.有点乱,没时间整理.当做记录用的.] 图片粘贴失效.没上传图,想要的直接下载文档吧. 项目目的:通过IIS,触摸屏,LCD模块实现音乐播放器功能(button上一首.下一首.播放. ...
- mini2440裸机试炼之——DMA直接存取 实现Uart(串口)通信
这个仅仅能作为自己初步了解MDA的开门篇 实现功能: 将字符串数据通过DMA0通道传递给UTXH0,然后在终端 显示.传输数据完后.DMA0产生中断,beep声, LED亮. DMA基本知识 计算机系 ...
- mini2440裸机试炼之—RTC闹钟中断,节拍中断
版权声明:博客地址:http://blog.csdn.net/muyang_ren.源代码能够在我的github上找看看 https://blog.csdn.net/muyang_ren/articl ...
- mini2440裸机试炼之——看门狗中断和复位操作
看门狗的工作原理: 设本系统程序完整执行一周期的时间是Tp,看门狗的定时周期为Ti,Ti>Tp,在程序正常执行时,定时器就不会溢出,若因为干扰等原因使系统不能在Tp时刻改动定时器的记数值,定时器 ...
- mini2440 裸机程序,下载到nand 里面,复制到 sdram 中不运行
按照韦东山的视频中 sdram的裸机代码,写了一份,通过 minitools 下载到 0x30000000,然后烧录到 nand中,接过不能正常运行. 尝试过多种方法后,只有一种解决方法,就是不要用 ...
- mini2440 裸机程序下载到 sdram 不能运行。
今天在 写了个简单的 led 的汇编程序,下载到 mini2440 的 nand flash 里面可以正常运行,但是下载到 sdram 里面不能运行. 后来发现有几个注意点, 要在 sdram 中运行 ...
- mini2440裸机之MMU(二)(mmu.c) (转)
分类: 嵌入式 http://blog.chinaunix.net/uid-26435987-id-3082166.html(转) /********************************* ...
- 八、mini2440裸机程序之UART(2)UART0与PC串口通信【转】
转自:http://blog.csdn.net/shengnan_wu/article/details/8309417 版权声明:本文为博主原创文章,未经博主允许不得转载. 1.相关原理图 2.相关寄 ...
- 八、mini2440裸机程序之UART(1)简单介绍【转】
转自:http://blog.csdn.net/shengnan_wu/article/details/8298869 一.概述 S3C2440通用异步接收和发送(UART)提供了三 ...
随机推荐
- Java多线程详解
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- 3-05. 寻求倒数第二链线性表K项目(15)(STL list应用 ZJU_PAT)
主题链接:http://pat.zju.edu.cn/contests/ds/3-05 给定一系列正整数,请设计一个尽可能高效的算法.查找倒数第K个位置上的数字. 输入格式说明: 输入首先给出一个正整 ...
- 让低版本的IE浏览器 强制渲染为IE8 或者 以上 浏览器模式
让低版本的IE浏览器 强制渲染为IE8 或者 以上 浏览器模式 那么就要用下面的方法:让网页兼容ie9 复制代码 代码如下: <!–[if lte IE 8]> <meta http ...
- VS2015安装
VS2015安装 Secondary Installer Setup Failed求解决方案 看到微软最近的一系列变化,着实让我等兴奋不已.VS2015下载地址就不说了.先来记录一下微软的几个变化吧. ...
- [译]关于Java 字符串最常被问到的十个问题
(说明,该文章翻译自Top 10 questions of Java Strings) 下面是关于Java字符串最常被问到的十个问题 1.怎么去比较字符串?使用==还是使用equals()? 简单来说 ...
- codeblock 设置背景颜色
今天觉得codeblock看着刺眼,想了想,能不能跟vs利用dark背景一样可以设置一个舒服的背景.于是就开始各种点击,各种摸索了. 1. 背景和各种颜色设置 不妨先说下vs中的设置是:工具(Tool ...
- Spring.Net+Nhibernate+Asp.Net Mvc 框架
搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (一)搭建你的环境 使用这套框架不是很长时间.但也基本应用了几个项目中了.在此和大家分享一下我是怎样一步一步搭建此框架 ...
- 基于Jquery 简单实用的弹出提示框
基于Jquery 简单实用的弹出提示框 引言: 原生的 alert 样子看起来很粗暴,网上也有一大堆相关的插件,但是基本上都是大而全,仅仅几句话可以实现的东西,可能要引入好几十k的文件,所以话了点时间 ...
- 数据结构队列的java实现,包括线性和链式两种方式
实现的思路为: 采用泛型的方式,首先定义了一个Queue的接口,然后通过实现该接口实现了线性和链式的两种形式的队列: 接口代码如下: package com.peter.java.dsa.interf ...
- Lex Yacc手册
Python Lex Yacc手册 本文是PLY (Python Lex-Yacc)的中文翻译版.转载请注明出处.这里有更好的阅读体验. 如果你从事编译器或解析器的开发工作,你可能对lex和yacc不 ...