S3C2440-IIC
时间:03-28
来源:互联网
点击:
IIC(Inter-Integrated Circuit,I2C)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微处理器及其外围设备,它的最主要优点是简单和有效。它只需要数据线SDA和时钟线SCL,就能够实现CPU与被控IC之间、IC与IC之间进行双向传送。
s3c2440内部有一个IIC总线接口,因此为我们连接带有IIC通信模块的外围设备提供了便利。它具有四种操作模式:主设备发送模式、主设备接收模式、从设备发送模式和从设备接收模式。在这里我们只把s3c2440当做IIC总线的主设备来使用,因此只介绍前两种操作模式。在主设备发送模式下,它的工作流程为:首先配置IIC模式,然后把从设备地址写入接收发送数据移位寄存器IICDS中,再把0xF0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号,如果想要继续发送数据,那么在接收到应答信号后,再把待发送的数据写入寄存器IICDS中,清除中断标志后,再次等待应答信号;如果不想再发送数据了,那么把0x90写入寄存器IICSTAT中,清除中断标志并等待停止条件后,即完成了一次主设备的发送。在主设备接收模式下,它的工作流程为:首先配置IIC模式,然后把从设备地址写入接收发送数据移位寄存器IICDS中,再把0xB0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号,如果想要接收数据,那么在应答信号后,读取寄存器IICDS,清除中断标志;如果不想接收数据了,那么就向寄存器IICSTAT写入0x90,清除中断标志并等待停止条件后,即完成了一次主设备的接收。在完成上述两个模式时,主要用到了控制寄存器IICCON、控制状态寄存器IICSTAT和发送接收数据移位寄存器IICDS。由于我们只把s3c2440当做主设备来用,并且系统的IIC总线上只有这么一个主设备,因此用来设置从设备地址的地址寄存器IICADD,和用于仲裁总线的多主设备线路控制寄存器IICLC都无需配置。寄存器IICCON的第6位和低4位用于设置IIC的时钟频率,因为IIC的时钟线SCL都是由主设备提供的。s3c2440的IIC时钟源为PCLK,当系统的PCLK为50MHz,而从设备最高需要100kHz时,可以将IICCON的第6位置1,IICCON的低4位全为0即可。寄存器IICCON的第7位用于设置是否发出应答信号,第5位用于是否使能发送和接收中断,第4位用于中断的标志,当接收或发送数据后一定要对该位进行清零,以清除中断标志。寄存器IICSTAT的高2位用于设置是哪种操作模式,当向第5位写0或写1时,则表示结束IIC或开始IIC通讯,第4位用于是否使能接收/发送数据。
#include "2440addr.h"
#define U32 unsigned int
unsigned char iic_buffer[8];
U32 length;
unsigned char add, word;
int cmd, flag, count, command;
void delay(int a)
{
int k;
for(k=0;k<a;k++)
;
}
void __irq UART0_ISR(void){
char ch;
rSRCPND |= (0x1<<28);
rINTPND |= (0x1<<28);
rSUBSRCPND |= 0x1<<0;
if(rUTRSTAT0 & 0x1){
ch = rURXH0;
while(!(rUTRSTAT0&0x4));
rUTXH0 = ch;
if(count == 0)
command = ch;
if(command == 0xa1){
if(count == 1){
add = ch;
}
else
if(count == 2){
word = ch;
}
else
if(count == 3){
length = ch;
}
else if(count >= 4)
{
iic_buffer[count-4] = ch;
if(count == length+3){
count = -1;
cmd = 0x01;
}
}
count++;
}
else if(command == 0xa2)
{
if(count == 1)
add = ch;
else
if(count == 2)
word = ch;
else
if(count == 3){
length = ch;
count = -1;
cmd = 0x02;
}
count++;
}
}
}
void __irq IIC_ISR(void){
rSRCPND |= 0x1<<27;
rINTPND |= 0x1<<27;
flag = 0;
}
void wrat24c02(unsigned char add,unsigned char word, U32 length){
int i;
flag = 1;
rIICDS = 0xa0; //dev add
rIICCON &= "(0x1<<4); //清中断
rIICSTAT = 0xf0; //主发送模式,写开始信号输出,IIC Rx/Tx使能
//等待ACK,接收器在接受到8位数据后,在第9个时钟周期,拉低SDA电平,然后会产生中断
while(flag == 1)
delay(100);
flag = 1;
rIICDS = word; //word add 发送要写入的数据的内存其实地址
rIICCON &= "(0x1<<4);
while(flag)
delay(100); //注意要有delay
for(i = 0; i < length; i++){
flag = 1;
rIICDS = iic_buffer[ i];
rIICCON &= "(0x1<<4);
while(flag)
delay(100);
}
rIICCON = 0xe0; //IIC应答有效,IICCLK=fpclk/512,IIC接受发送中断使能位
rIICSTAT = 0xd0; //主发送模式,rIICCON和rIICSTAT配置好,方便下次使用
}
void rdat24c02(unsigned char add, unsigned char word, U32 length){
int i;
char temp;
flag = 1;
rIICDS = add; //dev add
rIICCON &= "(0x1<<4);
rIICSTAT = 0xf0;
while(flag)
delay(100);
flag = 1;
rIICDS = word; //word add
rIICCON &= "(0x1<<4);
while(flag)
delay(100);
flag = 1;
//这里的IIC的随机读操作,根据IIC的随机读时序,先发启动,要读取的设备地址和写的内存地址,方向是写,即0,重启IIC,
//发要读取的设备地址,这次方向是读,然后接到ACK,从机向主机发data,主机相应ACK,直到最后一个data,主机不相应ACK,
//发送停止信号
rIICDS = add; //dev add
rIICSTAT = 0xb0; //改变方向为主接收
rIICCON &= "(0x1<<4);
while(flag)
delay(100);
flag = 1;
temp = rIICDS;
rIICCON &= "(0x1<<4);
while(flag)
delay(100);
for(i = 0; i < length; i++){
flag = 1;
if(i == (length - 1)){
rIICCON &= "(0x1<<7);
}
iic_buffer[ i] = rIICDS;
rIICCON &= "(0x1<<4);
while(flag)
delay(100);
}
rIICCON = 0xd0;
rIICSTAT = 0x90;
delay(200);
}
int Main(){
int i;
count= 0;
length = 0;
cmd = 0;
command = 0;
rGPECON = 0xa0000000; //GPE15~14 IICSDA,IICSCL
rGPEUP = 0xc000;
rIICCON = 0xe0; //IIC应答有效,IICCLK=fpclk/512,IIC接受发送中断使能位
rIICSTAT = 0x10; //IIC总线有效Rx/Tx
rULCON0 = 0x3;
rUCON0 = (1<<11)|(1<<2)|(1<<0);
rUBRdiv0 = 26;
rSRCPND = (0x1<<28)|(0x1<<27);
rINTPND = (0x1<<28)|(0x1<<27);
rSUBSRCPND = 0x1<<0;
rINTMSK &= "((0x1<<28)|(0x1<<27));
rINTSUBMSK &= "(0x1<<0);
pISR_UART0 = (U32)UART0_ISR;
pISR_IIC = (U32)IIC_ISR;
for(i = 0; i < 8; i++){
iic_buffer[ i] = 0xee;
}
while(1){
switch(cmd){
case 0x01:
cmd = 0;
wrat24c02(add, word, length);
break;
case 0x02:
cmd = 0;
rdat24c02(add, word, length);
for(i = 0; i < 8; i++){
while(!(rUTRSTAT0&0x4));
rUTXH0 = iic_buffer[ i];
}
break;
}
}
return 0;
}
作者:李万鹏
s3c2440内部有一个IIC总线接口,因此为我们连接带有IIC通信模块的外围设备提供了便利。它具有四种操作模式:主设备发送模式、主设备接收模式、从设备发送模式和从设备接收模式。在这里我们只把s3c2440当做IIC总线的主设备来使用,因此只介绍前两种操作模式。在主设备发送模式下,它的工作流程为:首先配置IIC模式,然后把从设备地址写入接收发送数据移位寄存器IICDS中,再把0xF0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号,如果想要继续发送数据,那么在接收到应答信号后,再把待发送的数据写入寄存器IICDS中,清除中断标志后,再次等待应答信号;如果不想再发送数据了,那么把0x90写入寄存器IICSTAT中,清除中断标志并等待停止条件后,即完成了一次主设备的发送。在主设备接收模式下,它的工作流程为:首先配置IIC模式,然后把从设备地址写入接收发送数据移位寄存器IICDS中,再把0xB0写入控制状态寄存器IICSTAT中,这时等待从设备发送应答信号,如果想要接收数据,那么在应答信号后,读取寄存器IICDS,清除中断标志;如果不想接收数据了,那么就向寄存器IICSTAT写入0x90,清除中断标志并等待停止条件后,即完成了一次主设备的接收。在完成上述两个模式时,主要用到了控制寄存器IICCON、控制状态寄存器IICSTAT和发送接收数据移位寄存器IICDS。由于我们只把s3c2440当做主设备来用,并且系统的IIC总线上只有这么一个主设备,因此用来设置从设备地址的地址寄存器IICADD,和用于仲裁总线的多主设备线路控制寄存器IICLC都无需配置。寄存器IICCON的第6位和低4位用于设置IIC的时钟频率,因为IIC的时钟线SCL都是由主设备提供的。s3c2440的IIC时钟源为PCLK,当系统的PCLK为50MHz,而从设备最高需要100kHz时,可以将IICCON的第6位置1,IICCON的低4位全为0即可。寄存器IICCON的第7位用于设置是否发出应答信号,第5位用于是否使能发送和接收中断,第4位用于中断的标志,当接收或发送数据后一定要对该位进行清零,以清除中断标志。寄存器IICSTAT的高2位用于设置是哪种操作模式,当向第5位写0或写1时,则表示结束IIC或开始IIC通讯,第4位用于是否使能接收/发送数据。
#include "2440addr.h"
#define U32 unsigned int
unsigned char iic_buffer[8];
U32 length;
unsigned char add, word;
int cmd, flag, count, command;
void delay(int a)
{
int k;
for(k=0;k<a;k++)
;
}
void __irq UART0_ISR(void){
char ch;
rSRCPND |= (0x1<<28);
rINTPND |= (0x1<<28);
rSUBSRCPND |= 0x1<<0;
if(rUTRSTAT0 & 0x1){
ch = rURXH0;
while(!(rUTRSTAT0&0x4));
rUTXH0 = ch;
if(count == 0)
command = ch;
if(command == 0xa1){
if(count == 1){
add = ch;
}
else
if(count == 2){
word = ch;
}
else
if(count == 3){
length = ch;
}
else if(count >= 4)
{
iic_buffer[count-4] = ch;
if(count == length+3){
count = -1;
cmd = 0x01;
}
}
count++;
}
else if(command == 0xa2)
{
if(count == 1)
add = ch;
else
if(count == 2)
word = ch;
else
if(count == 3){
length = ch;
count = -1;
cmd = 0x02;
}
count++;
}
}
}
void __irq IIC_ISR(void){
rSRCPND |= 0x1<<27;
rINTPND |= 0x1<<27;
flag = 0;
}
void wrat24c02(unsigned char add,unsigned char word, U32 length){
int i;
flag = 1;
rIICDS = 0xa0; //dev add
rIICCON &= "(0x1<<4); //清中断
rIICSTAT = 0xf0; //主发送模式,写开始信号输出,IIC Rx/Tx使能
//等待ACK,接收器在接受到8位数据后,在第9个时钟周期,拉低SDA电平,然后会产生中断
while(flag == 1)
delay(100);
flag = 1;
rIICDS = word; //word add 发送要写入的数据的内存其实地址
rIICCON &= "(0x1<<4);
while(flag)
delay(100); //注意要有delay
for(i = 0; i < length; i++){
flag = 1;
rIICDS = iic_buffer[ i];
rIICCON &= "(0x1<<4);
while(flag)
delay(100);
}
rIICCON = 0xe0; //IIC应答有效,IICCLK=fpclk/512,IIC接受发送中断使能位
rIICSTAT = 0xd0; //主发送模式,rIICCON和rIICSTAT配置好,方便下次使用
}
void rdat24c02(unsigned char add, unsigned char word, U32 length){
int i;
char temp;
flag = 1;
rIICDS = add; //dev add
rIICCON &= "(0x1<<4);
rIICSTAT = 0xf0;
while(flag)
delay(100);
flag = 1;
rIICDS = word; //word add
rIICCON &= "(0x1<<4);
while(flag)
delay(100);
flag = 1;
//这里的IIC的随机读操作,根据IIC的随机读时序,先发启动,要读取的设备地址和写的内存地址,方向是写,即0,重启IIC,
//发要读取的设备地址,这次方向是读,然后接到ACK,从机向主机发data,主机相应ACK,直到最后一个data,主机不相应ACK,
//发送停止信号
rIICDS = add; //dev add
rIICSTAT = 0xb0; //改变方向为主接收
rIICCON &= "(0x1<<4);
while(flag)
delay(100);
flag = 1;
temp = rIICDS;
rIICCON &= "(0x1<<4);
while(flag)
delay(100);
for(i = 0; i < length; i++){
flag = 1;
if(i == (length - 1)){
rIICCON &= "(0x1<<7);
}
iic_buffer[ i] = rIICDS;
rIICCON &= "(0x1<<4);
while(flag)
delay(100);
}
rIICCON = 0xd0;
rIICSTAT = 0x90;
delay(200);
}
int Main(){
int i;
count= 0;
length = 0;
cmd = 0;
command = 0;
rGPECON = 0xa0000000; //GPE15~14 IICSDA,IICSCL
rGPEUP = 0xc000;
rIICCON = 0xe0; //IIC应答有效,IICCLK=fpclk/512,IIC接受发送中断使能位
rIICSTAT = 0x10; //IIC总线有效Rx/Tx
rULCON0 = 0x3;
rUCON0 = (1<<11)|(1<<2)|(1<<0);
rUBRdiv0 = 26;
rSRCPND = (0x1<<28)|(0x1<<27);
rINTPND = (0x1<<28)|(0x1<<27);
rSUBSRCPND = 0x1<<0;
rINTMSK &= "((0x1<<28)|(0x1<<27));
rINTSUBMSK &= "(0x1<<0);
pISR_UART0 = (U32)UART0_ISR;
pISR_IIC = (U32)IIC_ISR;
for(i = 0; i < 8; i++){
iic_buffer[ i] = 0xee;
}
while(1){
switch(cmd){
case 0x01:
cmd = 0;
wrat24c02(add, word, length);
break;
case 0x02:
cmd = 0;
rdat24c02(add, word, length);
for(i = 0; i < 8; i++){
while(!(rUTRSTAT0&0x4));
rUTXH0 = iic_buffer[ i];
}
break;
}
}
return 0;
}
作者:李万鹏
总线 相关文章:
- 基于MSP430系列单片机的CAN总线接口转换卡设计(01-17)
- 各种通讯总线介绍(01-18)
- I2C总线原理及应用实例 (01-18)
- I2C总线在多机通信中的应用(01-17)
- 基于SPI总线的电能计量芯片ATT7022及其在配电监测终端的应用(01-18)
- CAN总线—PROFIBUS-DP总线网关的实现方法(01-17)