444 lines
11 KiB
C
444 lines
11 KiB
C
/********************************************************************************
|
||
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:长度为1Byte;1:长度为2Bytes
|
||
Length: 数据长度(不含CRC字节)
|
||
CrcFlg: Twi通讯是否支持CRC校验,0:不支持CRC,1:支持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:长度为1Byte;1:长度为2Bytes
|
||
Length: 数据长度(不含CRC字节)
|
||
CrcFlg: Twi通讯是否支持CRC校验,0:不支持CRC,1:支持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.5;SDA--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.5;SDA--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.5;SDA--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 |