/************************************************************************************/
/**********************************I2C DRIVER*****************************************/
/**************************JOJO.WANG.2013.07.23****************************************/
/************************************************************************************/
/**************************I2C Init****************************************************/
#include "stm8s_i2c.h"
#include "stm8s_clk.h"
#include "i2c.h"
#include "stm8s.h"
#include "stm8s_gpio.h"
#include "ui_wnd.h"
extern void C_Delay_Xms(U16 ms_cnt);
extern void C_Delay_5us(u16 nCount);
//================I2C FUNCTION================================
/*
void test(void)
{
GPIO_Init(SDA_GPIO, SDA_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(SLK_GPIO, SLK_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
C_Delay_Xms(10);
GPIO_Init(SDA_GPIO, SDA_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(SLK_GPIO, SLK_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
C_Delay_Xms(10);
GPIO_Init(SDA_GPIO, SDA_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(SLK_GPIO, SLK_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
C_Delay_Xms(10);
GPIO_Init(SDA_GPIO, SDA_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(SLK_GPIO, SLK_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
C_Delay_Xms(10);
GPIO_Init(SDA_GPIO, SDA_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(SLK_GPIO, SLK_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
C_Delay_Xms(10);
GPIO_Init(SDA_GPIO, SDA_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(SLK_GPIO, SLK_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
}
*/
void I2C_GPIO_Init(void)
{
SDA_GPIO->DDR |= (u8)SDA_PIN;
SLK_GPIO->DDR |= (u8)SLK_PIN;
GPIO_WriteHigh(SDA_GPIO, SDA_PIN);
GPIO_WriteHigh(SLK_GPIO, SLK_PIN);
}
// -\___
// ---\_
void I2C_Start(void)
{
GPIO_WriteHigh(SDA_GPIO, SDA_PIN);
GPIO_WriteHigh(SLK_GPIO, SLK_PIN);
C_Delay_Xms(10);
GPIO_WriteLow(SDA_GPIO, SDA_PIN);
C_Delay_Xms(10);
GPIO_WriteLow(SLK_GPIO, SLK_PIN);
}
// __/-
// _/-
void I2C_Stop(void)
{
GPIO_WriteLow(SDA_GPIO, SDA_PIN);
C_Delay_Xms(10);
GPIO_WriteHigh(SLK_GPIO, SLK_PIN);
C_Delay_Xms(10);
GPIO_WriteHigh(SDA_GPIO, SDA_PIN);
}
//--\__
//_____
void I2C_SetACK (void)
{
GPIO_WriteLow(SDA_GPIO, SDA_PIN);
C_Delay_Xms(10);
GPIO_WriteHigh(SLK_GPIO, SLK_PIN);
C_Delay_Xms(10);
GPIO_WriteLow(SLK_GPIO, SLK_PIN);
}
//--\__
//----
void I2C_SetNAK(void)
{
GPIO_WriteHigh(SDA_GPIO,SDA_PIN);
C_Delay_Xms(10);
GPIO_WriteHigh(SLK_GPIO, SLK_PIN);
C_Delay_Xms(10);
GPIO_WriteLow(SLK_GPIO, SLK_PIN);
}
BYTE I2C_Get_ACK(void)
{
BYTE i=0;
GPIO_WriteHigh(SDA_GPIO, SDA_PIN);
SDA_GPIO->DDR &= (u8)(~(SDA_PIN));
C_Delay_Xms(10);
GPIO_WriteHigh(SLK_GPIO, SLK_PIN);
C_Delay_Xms(10);
while((GPIO_ReadInputPin(SDA_GPIO, SDA_PIN))&&(i<200))
{
nop(); nop(); nop(); nop(); //0.5us
i++;
}
GPIO_WriteLow(SLK_GPIO, SLK_PIN);
SDA_GPIO->DDR |= (u8)SDA_PIN;
if(i>=200)
return 0;//ack fail
return 1; //ack ok
}
void I2C_Send_Byte(u8 data)
{
BYTE i;
BYTE bMask[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
/* MSB is sent first */
for(i=0;i<8;i++)
{
if (data&bMask[i])
{
GPIO_WriteHigh(SDA_GPIO, SDA_PIN);
}
else
{
GPIO_WriteLow(SDA_GPIO, SDA_PIN);
}
C_Delay_Xms(10);
GPIO_WriteHigh(SLK_GPIO, SLK_PIN);
C_Delay_Xms(10);
GPIO_WriteLow(SLK_GPIO, SLK_PIN);
}
}
BYTE I2C_Read_Byte(void)
{
BYTE i,tmpdata=0;
BYTE bMask[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
GPIO_WriteHigh(SDA_GPIO, SDA_PIN);
SDA_GPIO->DDR &= (u8)(~(SDA_PIN));
for(i=0;i<8;i++)
{
GPIO_WriteHigh(SLK_GPIO, SLK_PIN);
C_Delay_Xms(10);
if(GPIO_ReadInputPin(SDA_GPIO, SDA_PIN))
tmpdata+=bMask[i];
C_Delay_Xms(10);
GPIO_WriteLow(SLK_GPIO, SLK_PIN);
C_Delay_Xms(10);
}
SDA_GPIO->DDR |= (u8)SDA_PIN;
GPIO_WriteHigh(SDA_GPIO, SDA_PIN);
return tmpdata;
}
u8 MCU_WriteI2CToByte(u8 iDeviceAddr,u8 iAddr,u8 iData)
{
BYTE retry=0;
I2C_GPIO_Init();
I2C_ST_POS:
retry++;
if(retry>100) return 0;
I2C_Start();
I2C_Send_Byte(iDeviceAddr);
if(!I2C_Get_ACK()) goto I2C_ST_POS;
I2C_Send_Byte(iAddr);
if(!I2C_Get_ACK()) goto I2C_ST_POS;
I2C_Send_Byte(iData);
if(!I2C_Get_ACK()) goto I2C_ST_POS;
I2C_Stop();
return 1;
}
BYTE MCU_WriteStrToI2c(BYTE iDeviceAddr,BYTE iAddr,BYTE *iDataBuf,BYTE iLen,BYTE iLen_x)
{
BYTE i,j=0,retry=0;
I2C_GPIO_Init();
if(iLen<1) iLen=1;
j=iLen-1;
I2C_ST_POS:
retry++;
if(retry>100) return 0;
I2C_Start();
I2C_Send_Byte(iDeviceAddr);
if(!I2C_Get_ACK()) goto I2C_ST_POS;
I2C_Send_Byte(iAddr);
if(!I2C_Get_ACK()) goto I2C_ST_POS;
for(i=iLen_x;i<iLen;i++)
{
I2C_Send_Byte(iDataBuf[i]);
{
if(!I2C_Get_ACK()) goto I2C_ST_POS;
}
}
I2C_Stop();
return 1;
}
BYTE MCU_ReadStrFromI2C(BYTE iDeviceAddr,BYTE iAddr,BYTE *Rdata_buf,BYTE len,BYTE noregaddr)
{
BYTE retry=0;
BYTE i=0, j=0;
I2C_GPIO_Init();
I2C_ST_POS:
retry++;
if(retry>100) return 0;
//---------------------START----------------------------------
I2C_Start();
if (noregaddr==0)
{
//---------------------dAddr----------------------------------
I2C_Send_Byte(iDeviceAddr);
if(!I2C_Read_Byte()) goto I2C_ST_POS;
if(iDeviceAddr==0xA0)
C_Delay_Xms(3);
//----------------------iAddr---------------------------------
I2C_Send_Byte(iAddr);
if(!I2C_Read_Byte()) goto I2C_ST_POS;
if(iDeviceAddr==0xA0)
C_Delay_Xms(3);
I2C_Start();
}
I2C_Send_Byte(iDeviceAddr | 0x01);
if(!I2C_Read_Byte()) goto I2C_ST_POS;
for (i = 0; i < j; i++)
{
*Rdata_buf++ = I2C_Read_Byte();
I2C_SetACK();
}
//最后一个不传应答信号
if(iDeviceAddr==0xA0)
C_Delay_Xms(3);
*Rdata_buf = I2C_Read_Byte();
I2C_SetNAK();
I2C_Stop();
// C_Delay_Xms(3);
return 1;
}
#if 1
I2C_StruDef I2C1;
//=========内部高速时钟初始化===============
void Init_HSICLK(void)
{
CLK_DeInit(); //寄存器复位
CLK_HSICmd(ENABLE);
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8); //内部8分频2M
}
//=========外部高速时钟初始化===============
void Init_HSECLK(void)
{
// CLK_DeInit(); //寄存器复位
CLK_HSECmd(ENABLE) ; //外部时钟开,8M
CLK_ClockSwitchCmd(ENABLE); //切换使能
CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE,
CLK_CURRENTCLOCKSTATE_ENABLE); //开启时钟安全系统,当外部晶振损坏,自动转为内部2M时钟
}
void Switch_To_ExternClock(void)
{
CLK->ECKR = 0x01;//启动外部高速晶体振荡器, 允许外部高速振荡器工作
while((CLK->ECKR & 0x02) == 0x00); // 等待外部高速振荡器准备好
// 注意,复位后CPU 的时钟源来自内部的RC 振荡器
// for(;;) // 进入无限循环
{
// 下面将CPU 的时钟源切换到外部的高速晶体振荡器上,在开发板上的频率为8MHZ
CLK->SWCR = CLK->SWCR | 0x02; // SWEN <- 1
CLK->SWR = 0xB4; // 选择芯片外部的高速振荡器为主时钟
while((CLK->SWCR & 0x08) == 0); // 等待切换成功
CLK->SWCR = CLK->SWCR & 0xFD; // 清除切换标志
#if 0
// 下面将CPU 的时钟源切换到内部的RC 振荡器上,由于CLK_CKDIVR 的复位值为0x18
// 所以16MHZ 的RC 振荡器要经过8 分频后才作为主时钟,因此频率为2MHZ
CLK->SWCR = CLK->SWCR | 0x02; // SWEN <- 1
CLK->SWR = 0xE1; // 选择HSI 为主时钟源
while((CLK->SWCR & 0x08) == 0); // 等待切换成功
CLK->SWCR = CLK->SWCR & 0xFD; // 清除切换标志
#endif
}
}
void MCU_I2C_Init(void)
{
#if 0
CLK->PCKENR1 |= 0x01;
I2C->FREQR |= 0x10; //输入外设时钟频率为1MHz
I2C->CR1 = 0x00; //禁止I2C外设
I2C->CCRH &= ~0xcf;
I2C->CCRL &= ~0xff;
I2C->TRISER = 0x11;
I2C->CCRL = 0x10;
I2C->CCRH = 0x00;
I2C->CR1 |= 0x01; //开启I2C外设
I2C->CR2 |= 0x04; //当前接收字节返回应答
I2C->CR2 &= 0x08;
I2C->OARL = 0x86; //