本帖最后由 nixianmin 于 2011-11-13 07:37 编辑
好久没发帖子了,前段时间学了下LOOK,现在又回来用库函数试试。参考坛里的I2C帖子写了个I2C,调试成功。刚开始看官方例子,无从下手,后来参考多了,才开始下手,无非就是在I2C的中断里通过status状态码判断,并根据参考手册上的I2C数据传输模式的图来判断。我这个程序就是实现简单的I2C操作,用中断断点来看读取的数据,写的有点不好,只是实现罢了。
main.c
/*********************************************
//
//
**********************************************/
#include<stdio.h>
#include"NUC1xx.h"
#include"M0Base.h"
#include"DrvGPIO.h"
#include"M0Uart.h"
#include"M0Timer.h"
#include"lcd1602.h"
#include"m0rtc.h"
#include"M0I2c.h"
int main(void)
{
UNLOCKREG(); //解寄存器锁保护
PLL50M();
LOCKREG();
i2c_tr_buf[0]='0';
i2c_tr_buf[1]='1';
i2c_tr_buf[2]='2';
i2c_tr_buf[3]='3';
i2c_tr_buf[4]='4';
InitUart0();
InitTimer0();
InitLcd1602();
InitRtc();
InitI2c_Master();
Set_I2c_Start(0xa0,I2C_WRITE,10,0x0000);
Set_I2c_Start(0xa0,I2C_WRITE,0,0x0002); //不写数据,只写存储地址,和读数据一起用
Set_I2c_Start(0xa0,I2C_READ,5,0x00);//这里地址不起作用
while(1)
{
}
}
m0i2c.h
/*********************************************
//
//
**********************************************/
#ifndef _M0I2C_H_
#define _M0I2C_H_
#define I2C_READ 1
#define I2C_WRITE 0
extern uint8_t i2c_tr_buf[],i2c_re_buf[];
extern uint8_t i2c_flag;
void InitI2c_Master(void);
void Set_I2c_Start(int8_t ssalve,int8_t srw,int8_t snum,int16_t sadd);
#endif
m0i2c.c
/*********************************************
//
//
**********************************************/
#include"stdio.h"
#include"NUC1xx.h"
#include"DrvI2C.H"
#include"DrvGPIO.H"
#include"DrvSYS.h"
#include"m0i2c.h"
uint8_t i2c_tr_buf[10]={0};
uint8_t i2c_re_buf[10]={0};
uint8_t i2c_flag=0;
typedef struct{
int8_t i2c_salve; //传输从机地址
int8_t i2c_rw;
int8_t dat_num; //传输数据个数
int8_t dat_cnt; //传输数据数据计数
int16_t dat_add; //传输数据的其实地址
}I2C_TYPE;
volatile I2C_TYPE i2c={0,0,0,0};
//地址对读数据无效
//读数据只能先写地址,再读数据
void Set_I2c_Start(int8_t ssalve,int8_t srw,int8_t snum,int16_t sadd)
{
uint16_t cnt=0;
i2c.i2c_salve=ssalve;
i2c.i2c_rw=srw;
i2c.dat_num=snum;
i2c.dat_cnt=0;
i2c.dat_add=sadd;
i2c_flag=0 ;
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0);
while((i2c_flag!=1)&&(cnt!=0xffff))
cnt++;//判断是否读取或写结束
DrvSYS_Delay(8000);//延时
}
void I2c1CallBack(uint32_t status)
{
if(i2c.i2c_rw==I2C_READ) //读状态
{
if (status == 0x08) /* START has been transmitted and prepare SLA+W */
{
DrvI2C_WriteData(I2C_PORT1, (i2c.i2c_salve|0x01)); //读地址数据
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
}
else if (status == 0x40) /* SLA+R has been transmitted and ACK has been received */
{
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //have ack
}
else if(status==0x50)
{
i2c_re_buf[i2c.dat_cnt++] = DrvI2C_ReadData(I2C_PORT1);
if(i2c.dat_cnt<(i2c.dat_num-1))
{
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
}
else
{
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
}
}
else if (status == 0x58) /* DATA has been received and NACK has been returned */
{
i2c_re_buf[i2c.dat_cnt++] = DrvI2C_ReadData(I2C_PORT1);
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0);
i2c_flag=1;
}
else
{
printf("Status 0x%x is NOT processed\n", status);
}
}
else if(i2c.i2c_rw==I2C_WRITE) //写状态
{
if (status == 0x08) /* START has been transmitted */
{
DrvI2C_WriteData(I2C_PORT1, (i2c.i2c_salve&0xfe)); //读地址数据
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
}
else if (status == 0x18) /* SLA+W has been transmitted and ACK has been received */
{
DrvI2C_WriteData(I2C_PORT1, (int8_t)(i2c.dat_add)); //传输高位地址
i2c.dat_cnt++;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
}
else if (status == 0x20) /* SLA+W has been transmitted and NACK has been received */
{
DrvI2C_Ctrl(I2C_PORT1, 1, 1, 1, 0);
}
else if (status == 0x28) /* DATA has been transmitted and ACK has been received */
{
if (i2c.dat_cnt<2)
{
DrvI2C_WriteData(I2C_PORT1, (int8_t)(i2c.dat_add>>8));//传输低位地址
i2c.dat_cnt++;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
}
else if(i2c.dat_cnt<(i2c.dat_num+2))
{
DrvI2C_WriteData(I2C_PORT1, i2c_tr_buf[i2c.dat_cnt-2]);
i2c.dat_cnt++;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
}
else
{
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0);//send a stop
i2c_flag=1;
}
}
else
{
printf("Status 0x%x is NOT processed\n", status);
}
}
}
void InitI2c_Master()
{
DrvGPIO_InitFunction(E_FUNC_I2C1);
DrvI2C_Open(I2C_PORT1, 50000);
DrvI2C_EnableInt(I2C_PORT1);
DrvI2C_InstallCallback(I2C_PORT1, I2CFUNC, I2c1CallBack);
}
|