ZDBMS/code_drv/TWI.c

444 lines
11 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************************
Copyright (C), Sinowealth Electronic. Ltd.
Author: Sino
Version: V0.0
Date: 2020/04/26
History:
V2.0 2020/04/26 Preliminary
********************************************************************************/
#include "Main.h"
#ifdef TWI_Hardware_Module
U8 code CRC8Table[256]=
{ //120424-1 CRC Table
0x00,0x07,0x0E,0x09,0x1C,0x1B,0x12,0x15,0x38,0x3F,0x36,0x31,0x24,0x23,0x2A,0x2D,
0x70,0x77,0x7E,0x79,0x6C,0x6B,0x62,0x65,0x48,0x4F,0x46,0x41,0x54,0x53,0x5A,0x5D,
0xE0,0xE7,0xEE,0xE9,0xFC,0xFB,0xF2,0xF5,0xD8,0xDF,0xD6,0xD1,0xC4,0xC3,0xCA,0xCD,
0x90,0x97,0x9E,0x99,0x8C,0x8B,0x82,0x85,0xA8,0xAF,0xA6,0xA1,0xB4,0xB3,0xBA,0xBD,
0xC7,0xC0,0xC9,0xCE,0xDB,0xDC,0xD5,0xD2,0xFF,0xF8,0xF1,0xF6,0xE3,0xE4,0xED,0xEA,
0xB7,0xB0,0xB9,0xBE,0xAB,0xAC,0xA5,0xA2,0x8F,0x88,0x81,0x86,0x93,0x94,0x9D,0x9A,
0x27,0x20,0x29,0x2E,0x3B,0x3C,0x35,0x32,0x1F,0x18,0x11,0x16,0x03,0x04,0x0D,0x0A,
0x57,0x50,0x59,0x5E,0x4B,0x4C,0x45,0x42,0x6F,0x68,0x61,0x66,0x73,0x74,0x7D,0x7A,
0x89,0x8E,0x87,0x80,0x95,0x92,0x9B,0x9C,0xB1,0xB6,0xBF,0xB8,0xAD,0xAA,0xA3,0xA4,
0xF9,0xFE,0xF7,0xF0,0xE5,0xE2,0xEB,0xEC,0xC1,0xC6,0xCF,0xC8,0xDD,0xDA,0xD3,0xD4,
0x69,0x6E,0x67,0x60,0x75,0x72,0x7B,0x7C,0x51,0x56,0x5F,0x58,0x4D,0x4A,0x43,0x44,
0x19,0x1E,0x17,0x10,0x05,0x02,0x0B,0x0C,0x21,0x26,0x2F,0x28,0x3D,0x3A,0x33,0x34,
0x4E,0x49,0x40,0x47,0x52,0x55,0x5C,0x5B,0x76,0x71,0x78,0x7F,0x6A,0x6D,0x64,0x63,
0x3E,0x39,0x30,0x37,0x22,0x25,0x2C,0x2B,0x06,0x01,0x08,0x0F,0x1A,0x1D,0x14,0x13,
0xAE,0xA9,0xA0,0xA7,0xB2,0xB5,0xBC,0xBB,0x96,0x91,0x98,0x9F,0x8A,0x8D,0x84,0x83,
0xDE,0xD9,0xD0,0xD7,0xC2,0xC5,0xCC,0xCB,0xE6,0xE1,0xE8,0xEF,0xFA,0xFD,0xF4,0xF3
};
/*************************************************************************************************
* 函数名: CRC8cal
* 参 数: *p数据指针counter所需计算的长度
* 返回值: 无
* 描 述: CRC8就散
*************************************************************************************************/
U8 CRC8cal(U8 *p, U8 counter) //look-up table calculte CRC
{
U8 crc8 = 0;
for( ; counter > 0; counter--)
{
crc8 = CRC8Table[crc8^*p];
p++;
}
return(crc8);
}
/*************************************************************************************************
* 函数名: TWICheckStatus
* 参 数: Status当前TWI的状态
* 返回值: 无
* 描 述: 检测TWI的各个状态是否正常
*************************************************************************************************/
BOOL TWICheckStatus(U8 Status)
{
BOOL Result = 1;
U16 timeoutcount = 48000; //硬件IIC时timeoutcount大于100可正常通讯软件IIC建议保持原值 标准DEMO板
while((TWICON&0x08)==0) //等待TWI通讯结束
{
McuWDTClear(); //清除看门狗
if(timeoutcount)
{
timeoutcount--;
}
else
{
break;
}
}
if((TWISTA&0xf8) != Status)
{
Result = 0; //Error
}
return Result;
}
/*************************************************************************************************
* 函数名: TwiWrite
* 参 数: SlaveID: Slave ID
WrAddr: 写入地址
AddrType地址长度0长度为1Byte1长度为2Bytes
Length 数据长度不含CRC字节
CrcFlg Twi通讯是否支持CRC校验0不支持CRC1支持CRC
*WrBuf 写入数据存放地址
* 返回值: 无
* 描 述: Twi写入操作包括写入AFE支持CRC、RTC和EEPROM地址长度为2Bytes
*************************************************************************************************/
BOOL TwiWrite(U8 SlaveID, U16 WrAddr, U8 AddrType, U8 Length, U8 CrcFlg, U8 xdata *WrBuf)
{
U8 i;
U8 TempBuf[4];
BOOL Result = 1;
U16 timeoutcount = 48000;
TempBuf[0] = SlaveID;
TempBuf[1] = (U8)WrAddr;
TempBuf[2] = *WrBuf;
TempBuf[3] = CRC8cal(TempBuf, 3);
if(Length > 0)
{
HTimeoutChk();
TWICON = 0x60; //Start
if((!TWICheckStatus(0x08))&&(!TWICheckStatus(0x10)))
{
Result = 0;
goto WrErr;
}
TWIDAT = SlaveID; //Slave地址
TWICON = 0x40;
if(!TWICheckStatus(0x18))
{
Result = 0;
goto WrErr;
}
if(AddrType == TWI_ADDR_2B)
{
TWIDAT = (U8)(WrAddr>>8); //写寄存器高字节地址-仅针对外挂EEPROM
TWICON = 0x40;
if(!TWICheckStatus(0x28))
{
Result = 0;
goto WrErr;
}
}
TWIDAT = (U8)WrAddr; //写寄存器地址
TWICON = 0x40;
if(!TWICheckStatus(0x28))
{
Result = 0;
goto WrErr;
}
if(CrcFlg == TWI_CRC_YES) //如果是写AFE寄存器则固定写一个字节+CRC
{
TWIDAT = *WrBuf; //Write Data
TWICON = 0x40;
if(!TWICheckStatus(0x28))
{
Result = 0;
goto WrErr;
}
TWIDAT = TempBuf[3]; //Write CRC
TWICON = 0x40;
if(!TWICheckStatus(0x28))
{
Result = 0;
goto WrErr;
}
}
else //写EEPROM和RTC
{
for(i=0; i<Length; i++)
{
TWIDAT = *WrBuf;
TWICON = 0x40;
if(!TWICheckStatus(0x28))
{
Result = 0;
goto WrErr;
}
WrBuf++;
}
}
WrErr:
TWICON = 0x50;
while((TWICON&0x10)!=0)
{
McuWDTClear(); //清除看门狗
if(timeoutcount)
{
timeoutcount--;
}
else
{
break;
}
}
}
return Result;
}
/*************************************************************************************************
* 函数名: TwiRead
* 参 数: SlaveID: Slave ID
RdAddr: 读取地址
AddrType地址长度0长度为1Byte1长度为2Bytes
Length 数据长度不含CRC字节
CrcFlg Twi通讯是否支持CRC校验0不支持CRC1支持CRC
*RdBuf 读取数据存放地址
* 返回值: 无
* 描 述: Twi读取操作包括读取AFE支持CRC、RTC和EEPROM地址长度为2Bytes
*************************************************************************************************/
BOOL TwiRead(U8 SlaveID, U16 RdAddr, U8 AddrType, U8 Length, U8 CrcFlg, U8 xdata *RdBuf)
{
BOOL Result = 1;
U8 i;
U8 xdata TempBuf[46]; //AFE一次性读取2Bytes+CRC
U8 RdCrc = 0;
U16 timeoutcount = 48000;
TempBuf[0] = SlaveID; //缓存到TempBuf主要是为了计算CRC仅用于AFE读取
TempBuf[1] = (U8)RdAddr;
//TempBuf[2] = Length;
TempBuf[2] = SlaveID | 0x01;
if(Length > 0)
{
HTimeoutChk();
TWICON = 0x60; //Start
if((!TWICheckStatus(0x08))&&(!TWICheckStatus(0x10)))
{
Result = 0;
goto RdErr;
}
TWIDAT = SlaveID; //发送Slave写地址
TWICON = 0x40;
if(!TWICheckStatus(0x18))
{
Result = 0;
goto RdErr;
}
if(AddrType == TWI_ADDR_2B) //地址为2Bytes
{
TWIDAT = (U8)(RdAddr>>8); //读寄存器高字节地址-仅针对外挂EEPROM
TWICON = 0x40;
if(!TWICheckStatus(0x28))
{
Result = 0;
goto RdErr;
}
}
TWIDAT = (U8)RdAddr; //发送寄存器低字节地址
TWICON = 0x40;
if(!TWICheckStatus(0x28))
{
Result = 0;
goto RdErr;
}
// if(SlaveID != AFE_ID)
// {
// TWIDAT = Length; //发送读取数据长度
// TWICON = 0x40;
// if(!TWICheckStatus(0x28))
// {
// Result = 0;
// goto RdErr;
// }
// }
TWICON = 0x60; //发送RStart
if((!TWICheckStatus(0x08))&&(!TWICheckStatus(0x10)))
{
Result = 0;
goto RdErr;
}
TWIDAT = SlaveID|0x01; //发送Slave读地址
TWICON = 0x40;
if(!TWICheckStatus(0x40))
{
Result = 0;
goto RdErr;
}
for(i=0; i<Length; i++)
{
if((CrcFlg == TWI_CRC_NO)) //不支持CRC
{
if(i == Length-1)
{
TWICON = 0x40; //发送NACK最后一次读
TWICheckStatus(0x58);
}
else
{
TWICON = 0x44; //发送ACK继续读
TWICheckStatus(0x50);
}
*RdBuf = TWIDAT;
RdBuf++;
}
else //支持CRC的现将数据放在临时Buf
{
TWICON = 0x44; //ACK
TWICheckStatus(0x50);
TempBuf[3+i] = TWIDAT;
}
}
if(CrcFlg == TWI_CRC_YES)
{
TWICON = 0x40; //No ACK
TWICheckStatus(0x58);
RdCrc = TWIDAT;
if(RdCrc == CRC8cal(TempBuf, 3+Length))
{
for(i=0; i<Length; i++)
{
*RdBuf = TempBuf[3+i];
RdBuf++;
}
}
else
{
Result = 0;
goto RdErr;
}
}
RdErr:
TWICON = 0x50; //TWI Stop
while((TWICON&0x10)!=0)
{
McuWDTClear(); //清除看门狗
if(timeoutcount)
{
timeoutcount--;
}
else
{
break;
}
}
}
return Result;
}
/*************************************************************************************************
* 函数名: TwiInit
* 参 数: FreqKHz: 设置TWI通讯频率
* 返回值: 无
* 描 述: 初始化TWI的映射IO及通讯频率等
//*************************************************************************************************/
//void TwiInit(void)
//{
// TWICR = 0x32; //默认配置SCL--P0.5SDA--P0.4
// TWITOUT = 0x00; //外部有上拉电阻,故芯片内部上拉不用使能
// TWIBR = (24000/TWI_FREQ_KHz-16)/2/1; //配置发送波特率禁止总线超时判断f=fsys/(16+2*CR*TWIBR)=24MHz/(16+2*16*TWIBR)=**KHz
// TWISTA = 0x06; //16分频
// TWICON = 0x40; //ENTWI ,禁止高电平超时
// TWTFREE = 0xff; //最大超时配置
// TWIDAT = 0x00;
//}
void TwiInit(void)
{
TWICR = 0x32; //默认配置SCL--P0.5SDA--P0.4
TWITOUT = 0x00; //外部有上拉电阻,故芯片内部上拉不用使能
TWISTA = 0x00;
TWIBR = (8000/TWI_FREQ_KHz-16)/2/1; //配置发送波特率禁止总线超时判断f=fsys/(16+2*CR*TWIBR)=24MHz/(16+2*16*TWIBR)=**KHz
TWISTA = 0x02; //16分频
// #if ((TWI_FREQ_KHz >= 10)&&(TWI_FREQ_KHz <= 400))
// {
// #if TWIBR1 < 256
// TWIBR = TWIBR1;
// TWISTA |= 0x06;
// #elif TWIBR2 < 256
// TWIBR = TWIBR2;
// TWISTA |= 0x04;
// #elif TWIBR3 < 256
// TWIBR = TWIBR3;
// TWISTA |= 0x02;
// #elif TWIBR4 < 256
// TWIBR = TWIBR4;
// TWISTA |= 0x00;
// #endif
// }
// #else
// {
// #error: "Please enter a number(TWI_FREQ_KHz) from 10 to 400!";
// }
//
// #endif
TWICON = 0x40; //ENTWI ,禁止高电平超时
TWTFREE = 0xff; //最大超时配置
TWIDAT = 0x00;
}
//void TwiInit(void)
//{
// U16 i,k;
// U8 j;
// TWICR = 0x32; //默认配置SCL--P0.5SDA--P0.4
// TWITOUT = 0x00; //外部有上拉电阻,故芯片内部上拉不用使能
// i = (24000/TWI_FREQ_KHz-16)/2; //配置发送波特率禁止总线超时判断f=fsys/(16+2*CR*TWIBR)=24MHz/(16+2*16*TWIBR)=**KHz
// for(j=1;j<4;j++)
// {
// k =1<<(2*j-2);
// if(i / k <= 255)
// {
// TWIBR = i / k;
// switch (j)
// {
// case 1:
// TWISTA = 0x00;
// break;
//
// case 2:
// TWISTA = 0x02;
// break;
//
// case 3:
// TWISTA = 0x04;
// break;
//
// case 4:
// TWISTA = 0x06;
// break;
// }
// goto loop;
// }
// }
//loop:
//// TWISTA = 0x06; //16分频
// TWICON = 0x40; //ENTWI ,禁止高电平超时
// TWTFREE = 0xff; //最大超时配置
// TWIDAT = 0x00;
//}
#endif