我在调TEL6621的时候的一个I2C 程序。用的是中断
注意: TEL6621 的I2C read 是如下这样的
start ADDR D0 D1 D2 D3 STOP
I2C.C
#include "main.h"
I2C_StruDef I2C1;
void Bsp_I2CInit(void)
{
CLK_PCKENR1 |= 0x01;
I2C_CR1 = 0x00; //禁用I2C外设
//如果需产生100k的时钟,假始输入时钟为8MHz,则Tck = 125ns.
//因为100k时钟半个周期为5us(5000ns), CCR = 5000/125 = 40(28h)
I2C_FREQR = 16; //输入外设时钟频率为16MHz (如果设置为8M, 实际输入是16M时,I2C时钟以16M为准)
I2C_CCRH = 0x00; //标准模式
I2C_CCRL = 0x50;
//标准模式下,最大允许上升时间为1000ns, 因为Tck = 125ns,
//则TRISER = (1000 / 125 + 1) = 9
I2C_TRISER = 0x09; //设置上升时间
I2C_CR1 = 0x01; //开启I2C外设
}
void Bsp_I2CWrite(uint8_t Dev_Addr, uint8_t Sub_Addr, uint8_t* pdata, uint16_t num)
{
if(0x02 == (I2C_SR3 & 0x02))
{
;
}
else
{
I2C1.State = I2C_WRITEMODE;
I2C1.DeviceAddr = Dev_Addr;
I2C1.SubAddr = Sub_Addr;
I2C1.Tx_I2C_Buf = pdata;
I2C1.Tx_Cnt = num;
I2C1.Rx_Cnt = 0;
I2C1.Cnt = 0;
I2C_ITR = 0x07; //使能事件和出错中断, 缓冲中断
I2C_CR2 = 0x01; //产生开始位
}
}
void Bsp_I2CRead(uint8_t Dev_Addr, uint8_t Sub_Addr, uint8_t* pdata, uint16_t num)
{
if(0x02 == (I2C_SR3 & 0x02))
{
;
}
else
{
I2C1.State = I2C_READMODE;
I2C1.DeviceAddr = Dev_Addr;
I2C1.SubAddr = Sub_Addr;
I2C1.Rx_I2C_Buf = pdata;
I2C1.Rx_Cnt = num;
I2C1.Tx_Cnt = 0;
I2C1.Cnt = 0;
I2C_ITR = 0x07; //使能事件和出错中断, 缓冲中断
I2C_CR2 = 0x01; //产生开始位
}
TIM2DlyHMSM(0, 0, 0, 10);
}
void I2C_Interrupt_Handler(void)
{
uint8_t temp;
if(0x01 == (I2C_SR1 & 0x01)) //EV5, 开始位已发送
{
temp = I2C_SR1;
if(I2C_WRITEMODE == I2C1.State)
I2C_DR = I2C1.DeviceAddr & 0xfe;
else if(I2C_READMODE == I2C1.State)
I2C_DR = I2C1.DeviceAddr | 0x01;
else;
}
else if(0x02 == (I2C_SR1 & 0x02)) //EV6, 器件地址已发送
{
temp = I2C_SR1;
temp = I2C_SR3;
if(I2C_WRITEMODE == I2C1.State)
I2C_DR = I2C1.SubAddr;
else if(I2C_READMODE == I2C1.State)
{
if(I2C1.Rx_Cnt > 1) I2C_CR2 = 0x04;
else if(I2C1.Rx_Cnt == 1) I2C_CR2 = 0x00;
else I2C_CR2 = 0x02; //产生STOP位
}
else;
}
else if(0x40 == (I2C_SR1 & 0x40)) //EV7
{
if(I2C1.Cnt < (I2C1.Rx_Cnt - 1))
{
I2C1.Rx_I2C_Buf[I2C1.Cnt] = I2C_DR;
I2C1.Cnt++;
if(I2C1.Cnt == (I2C1.Rx_Cnt - 1))
{
I2C_CR2 = 0x02; //产生STOP位, no ack
}
}
else if(I2C1.Cnt == (I2C1.Rx_Cnt - 1))
{
I2C1.Rx_I2C_Buf[I2C1.Cnt] = I2C_DR;
}
else;
}
else if(0x80 == (I2C_SR1 & 0x80)) //EV8
{
temp = I2C_SR1;
if(I2C1.Cnt < I2C1.Tx_Cnt)
{
I2C_DR = I2C1.Tx_I2C_Buf[I2C1.Cnt];
I2C1.Cnt++;
}
else
{
I2C_CR2 = 0x02; //产生STOP位
}
}
else
{
printf("\r\n I2C_SR1 = %x", (uint16_t)I2C_SR1);
temp = I2C_SR1;
}
if(I2C_SR2)
{
printf("\r\n I2C_SR2 = %x", (uint16_t)I2C_SR2);
I2C_SR2 = 0;
}
}
I2C.H
#ifndef _BSP_I2C_H_
#define _BSP_I2C_H_
#define I2C_WRITEMODE 0
#define I2C_READMODE 1
typedef struct
{
uint8_t State;
uint16_t Cnt;
uint16_t Rx_Cnt, Tx_Cnt;
uint8_t DeviceAddr;
uint8_t SubAddr;
uint8_t *Rx_I2C_Buf;
uint8_t *Tx_I2C_Buf;
}I2C_StruDef;
extern I2C_StruDef I2C1;
void Bsp_I2CInit(void);
void Bsp_I2CWrite(uint8_t Dev_Addr, uint8_t Sub_Addr, uint8_t* pdata, uint16_t num);
void Bsp_I2CRead(uint8_t Dev_Addr, uint8_t Sub_Addr, uint8_t* pdata, uint16_t num);
void I2C_Interrupt_Handler(void);
#endif
|