本帖最后由 denvice 于 2011-7-13 12:11 编辑
看多了大家奉献的帖子,这里我也奉献一帖,虽然新唐单片机的IIC够多,但是我实在是无聊呵呵写了一个GPIO模拟IIC的程序,和大家一起来学习学习。
/************************************
函数功能:通过PA.0,PA.2向2404写入和
读出单字节数据。写入以后将数据读出来,
如果写进去的数据和读出来的数据相等,
则让PB.0的LED闪烁起来
*************************************/
#include <stdio.h>
#include "NUC1xx.h"
#include "DrvGPIO.h"
#include "DrvSYS.h"
void start(void) //起始信号
{
DrvGPIO_SetBit(E_GPA, 0); //sda=1
DrvSYS_Delay(5); //延时5us
DrvGPIO_SetBit(E_GPA, 2); //scl=1
DrvSYS_Delay(5); //延时5us
DrvGPIO_ClrBit(E_GPA, 0); //sda=0
DrvSYS_Delay(5); //延时5us
}
void stop(void) //停止信号
{
DrvGPIO_ClrBit(E_GPA, 0); //sda=0
DrvSYS_Delay(5); //延时5us
DrvGPIO_SetBit(E_GPA, 2); //scl=1
DrvSYS_Delay(5); //延时5us
DrvGPIO_SetBit(E_GPA, 0); //sda=1
DrvSYS_Delay(5); //延时5us
}
void waitack(void)//等待应答信号
{
int i;
DrvGPIO_SetBit(E_GPA, 2); //scl=1
DrvSYS_Delay(5); //延时5us
DrvGPIO_Open(E_GPA,0, E_IO_INPUT); //将sda置为输入
while(DrvGPIO_GetBit(E_GPA,0)&&i<255)
i++;
DrvGPIO_Open(E_GPA,0, E_IO_OUTPUT);//将sda置为输出
DrvGPIO_ClrBit(E_GPA, 2); //scl=0
DrvSYS_Delay(5); //延时5us
}
void noack(void) //非应答信号
{
DrvGPIO_SetBit(E_GPA, 0); //sda=1
DrvSYS_Delay(5); //延时5us
DrvGPIO_SetBit(E_GPA, 2); //scl=1
DrvSYS_Delay(5); //延时5us
DrvGPIO_ClrBit(E_GPA, 2); //scl=0
DrvSYS_Delay(5); //延时5us
DrvGPIO_ClrBit(E_GPA, 0); //sda=0
DrvSYS_Delay(5);
}
void ack(void) //应答信号
{
DrvGPIO_ClrBit(E_GPA, 0); //sda=0
DrvSYS_Delay(5); //延时5us
DrvGPIO_SetBit(E_GPA, 2); //scl=1
DrvSYS_Delay(5); //延时5us
DrvGPIO_ClrBit(E_GPA, 2); //scl=0
DrvSYS_Delay(5); //延时5us
DrvGPIO_SetBit(E_GPA, 0); //sda=1
DrvSYS_Delay(5);
}
void write8bit(int input) //写一个字节数据
{
int i;
DrvGPIO_ClrBit(E_GPA, 2); //scl=0
DrvSYS_Delay(5); //延时5us
for(i=0;i<8;i++)
{
if((input<<i)&0x80)
DrvGPIO_SetBit(E_GPA, 0); //sda=1
else
DrvGPIO_ClrBit(E_GPA, 0); //sda=0
DrvSYS_Delay(5); //延时5us
DrvGPIO_SetBit(E_GPA, 2); //scl=1
DrvSYS_Delay(5); //延时5us
DrvGPIO_ClrBit(E_GPA, 2); //scl=0
DrvSYS_Delay(5);
}
DrvGPIO_ClrBit(E_GPA, 2); //scl=0
DrvSYS_Delay(5); //延时5us
DrvGPIO_SetBit(E_GPA, 0); //sda=1
DrvSYS_Delay(5); //延时5us
}
int read8bit(void) //读一个字节数据
{
int temp,rbyte=0;
DrvGPIO_Open(E_GPA,0, E_IO_INPUT); //将sda置为输入
for(temp=0;temp<8;temp++)
{
rbyte=rbyte<<1;
if(DrvGPIO_GetBit(E_GPA,0))
rbyte=rbyte|0x01; //延时5us
DrvGPIO_SetBit(E_GPA, 2); //scl=1
DrvSYS_Delay(5); //延时5us
DrvGPIO_ClrBit(E_GPA, 2); //scl=0
DrvSYS_Delay(5);
}
DrvGPIO_Open(E_GPA,0, E_IO_OUTPUT);//将sda置为输出
DrvGPIO_ClrBit(E_GPA, 2); //scl=0 //调试连续读操作时发现不能将SCL拉高读完一次数据后
DrvGPIO_SetBit(E_GPA, 0); //sda=1
DrvSYS_Delay(5); //延时5us
return(rbyte);
}
void init(void)
{
DrvGPIO_SetBit(E_GPA, 0); //sda=1
DrvGPIO_SetBit(E_GPA, 2); //scl=1
}
void writebyte(int add,int dat) //将一个字节数据dat写入某个地址add
{
start();
if(add>=256) //2402的地址是A0,但是2404的高256位地址为A2
write8bit(0xA2);
else
write8bit(0xA0);
waitack();
if(add>=256)
write8bit(add-256);
else
write8bit(add);
waitack();
write8bit(dat);
waitack();
stop();
}
int readbyte(char add)
{
int byte;
start();
if(add>=256)
write8bit(0xA2);
else
write8bit(0xA0);
waitack();
if(add>=256)
write8bit(add-256);
else
write8bit(add);
waitack();
start();
if(add<256)
write8bit(0xA1);
else
write8bit(0xA3);
waitack();
byte=read8bit();
noack();
stop();
return byte;
}
void delay_loop(void)
{
uint32_t j;
for(j=0;j<60000;j++);
for(j=0;j<60000;j++);
for(j=0;j<60000;j++);
for(j=0;j<60000;j++);
}
int main()
{
int a;
UNLOCKREG(x); //解锁
DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1); //配置晶振
DrvSYS_Delay(5000);
LOCKREG(x);
DrvGPIO_Open(E_GPA, 0, E_IO_OUTPUT);//将管脚配置为输出
DrvGPIO_Open(E_GPA, 2, E_IO_OUTPUT);//
DrvGPIO_Open(E_GPA, 4, E_IO_OUTPUT);//
DrvGPIO_Open(E_GPB, 0, E_IO_OUTPUT);//
writebyte(20,3); //将3写入2402的地址20的寄存器中
delay_loop();
a=readbyte(20); //读取2402地址20处的数据
while(1)
{
if(a==3)
{
DrvGPIO_ClrBit(E_GPB,0);
delay_loop();
DrvGPIO_SetBit(E_GPB,0);
delay_loop();
}
}
} |