EEPROM和RAM寄存器读写协议如下
twi.c
#include "twi.h"
unsigned char const CRC8Table[]=
{ //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
};
void Delay4us(void) //4uS
{
uint32_t ticks;
uint32_t told,tnow,reload,tcnt=0;
reload = SysTick->LOAD; //获取重装载寄存器值
ticks = 4 * (SystemCoreClock / 1000000); //计数时间值 括号里的代表1us秒嘀嗒定时器的value会向下降多少值
told=SysTick->VAL; //获取当前数值寄存器值(开始时数值)
while(1)
{
tnow=SysTick->VAL; //获取当前数值寄存器值
if(tnow!=told) //当前值不等于开始值说明已在计数
{
if(tnow<told) //当前值小于开始数值,说明未计到0
tcnt+=told-tnow; //计数值=开始值-当前值
else //当前值大于开始数值,说明已计到0并重新计数
tcnt+=reload-tnow+told; //计数值=重装载值-当前值+开始值 (已从开始值计到0)
told=tnow; //更新开始值
if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
}
}
}
void TWI_Init(void)
{
rcu_periph_clock_enable(RCU_GPIOB);
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
TWI_DAT_HIGH;
TWI_CLK_HIGH;
}
void TwiStart(void)
{
TWI_DAT_HIGH;
TWI_CLK_HIGH;
TWI_DAT_OUT;
TWI_CLK_OUT;
TWI_DAT_LOW;
Delay4us();
TWI_CLK_LOW;
}
void TwiReStart(void)
{
TWI_DAT_HIGH;
TWI_CLK_HIGH;
Delay4us();
TWI_DAT_LOW;
Delay4us();
TWI_CLK_LOW;
}
void TwiStop(void)
{
TWI_DAT_OUT;
TWI_DAT_LOW;
Delay4us();
TWI_CLK_HIGH;
Delay4us();
TWI_DAT_HIGH;
Delay4us();
TWI_DAT_IN;
TWI_CLK_IN;
}
//SH367309接收好数据后,释放SCL信号线,所以此函数可以判断通信是否成功
unsigned char TwiChkClkRelease(void)
{
unsigned int TimeoutCnt=1000; //If Clock is not released within 4ms, is considered overtime
unsigned char result=0;
TWI_CLK_IN;
while(TimeoutCnt--)
{
Delay4us();
if(TWI_RD_CLK)
{
result = 1;
break;
}
}
TWI_CLK_HIGH;
TWI_CLK_OUT;
return result;
}
unsigned char TwiSendData(unsigned char Data, unsigned char Clk**)
{
unsigned char i;
unsigned char result=0;
//1. After sending the Start signal, there is no need to detect Clock is released, And sending the first bit
if(Data&0x80)
{
TWI_DAT_HIGH;
}
else
{
TWI_DAT_LOW;
}
if(Clk** == 1)
{
Delay4us();
if(TwiChkClkRelease())
{
TWI_CLK_LOW;
}
else
{
return result;//返回0表示通信失败
}
}
else
{
Delay4us();
TWI_CLK_HIGH;
Delay4us();
TWI_CLK_LOW;
}
//2. Send the remaining seven bit
Data = Data<<1;
for(i=0; i<7; i++)
{
if(Data&0x80)
{
TWI_DAT_HIGH;
}
else
{
TWI_DAT_LOW;
}
Data = Data<<1;
Delay4us();
TWI_CLK_HIGH;
Delay4us();
TWI_CLK_LOW;
}
TWI_DAT_IN;
Delay4us();
for(i=0; i<10; i++)
{
if(TWI_RD_DAT == 0)
{
result = 1;
break;
}
}
TWI_CLK_HIGH;
Delay4us();
TWI_DAT_LOW;
TWI_DAT_OUT;
TWI_CLK_LOW;
Delay4us();
return result;//返回1有应答,返回0无应答
}
unsigned char TwiGetData(unsigned char Ack**)
{
unsigned char i, RdData=0;
TWI_DAT_IN;
Delay4us();
for(i=0; i<8; i++)
{
TWI_CLK_HIGH;
Delay4us();
if(TWI_RD_DAT)
{
RdData |= (1<<(7-i));
}
TWI_CLK_LOW;
Delay4us();
}
TWI_DAT_OUT;
if(Ack** != 0)
{
TWI_DAT_LOW;
}
else
{
TWI_DAT_HIGH;
}
TWI_CLK_HIGH;
Delay4us();
TWI_CLK_LOW;
Delay4us();
return RdData;
}
unsigned char CRC8cal(unsigned char *p, unsigned char Length) //look-up table calculte CRC
{
unsigned char crc8 = 0;
for(; Length > 0; Length--)
{
crc8 = CRC8Table[crc8^*p];
p++;
}
return(crc8);
}
unsigned char TwiWrite(unsigned char SlaveID, unsigned int WrAddr, unsigned char Length, unsigned char *WrBuf)
{
unsigned char i;
unsigned char TempBuf[4];
unsigned char result = 0;
TempBuf[0] = SlaveID;
TempBuf[1] = (unsigned char)WrAddr;
TempBuf[2] = *WrBuf;
TempBuf[3] = CRC8cal(TempBuf, 3);
if(Length > 0)
{
TwiStart();
if(!TwiSendData(SlaveID, 1)) //Send Slave ID
{
goto WrErr;
}
if(TwiSendData(WrAddr, 0)) //Send Write Address(Low 8bit)
{
result = 1;
for(i=0; i<Length; i++)
{
if(TwiSendData(*WrBuf, 0)) //Send Write Data
{
WrBuf++;
}
else
{
result = 0;
break;
}
}
if(!TwiSendData(TempBuf[3], 0)) //write CRC
{
result = 0;
}
}
WrErr:
TwiStop();
}
return result;
}
unsigned char TwiRead(unsigned char SlaveID, unsigned int RdAddr, unsigned char Length, unsigned char *RdBuf)
{
unsigned char i;
unsigned char result=0;
unsigned char TempBuf[46];
unsigned char RdCrc=0;
TempBuf[0] = SlaveID;
TempBuf[1] = (unsigned char)RdAddr;
TempBuf[2] = Length;
TempBuf[3] = SlaveID | 0x01;
if(Length > 0)
{
TwiStart(); //开始
if(!TwiSendData(SlaveID, 1)) //Send Slave ID
{
goto RdErr;
}
if(!TwiSendData(RdAddr, 0)) //Send Read Address(Low 8bit)
{
goto RdErr;
}
if(!TwiSendData(Length, 0))
{
goto RdErr;
}
TwiReStart();
if(TwiSendData(SlaveID|0x1, 0)) //Send Slave ID
{
result = 1;
for(i=0; i<Length+1; i++)
{
if(i == Length)
{
RdCrc = TwiGetData(0); //Get Data
}
else
{
TempBuf[4+i] = TwiGetData(1); //Get Data
}
}
if(RdCrc != CRC8cal(TempBuf, 4+Length))
{
result = 0;
}
else
{
for(i=0; i<Length; i++)
{
*RdBuf = TempBuf[4+i];
RdBuf++;
}
}
}
RdErr:
TwiStop();
}
return result;
}
/*特别注意,写eeprom必须要使能烧写模式,其他的读eeprom,ram或者写ram正常即可
void WriteAFEData_EEPROM()
{
TwiRead(0x34,0X00,26,tagBMS.ucReadAFERegister); //读AFE的EEPROM寄存器,地址(00H-19H 即 0-25),共26个8位寄存器
if(memcmp(tagBMS.ucWriteAFERegister,tagBMS.ucReadAFERegister,25)!=0) //存储区str1、str2前n个字节比较,0=无区别,!=0有区别
{
UCHAR i;
SH367309_VPRO_Hi; //使能AFE的VPRO烧写功能(可以对EEPROM进行配置)
delay_1ms(100); //延时,等待电平稳定
for(i=0; i<25; i++) //写AFE的EEPROM寄存器,地址(00H-19H 即 0-25),共26个8位寄存器
{
delay_1ms(5);
if(!TwiWrite(0x34, i, 1, tagBMS.ucWriteAFERegister+i))
{
tagSBS.bAFEFaultStatus = ISYES;//写AFEROM出现错误
}
}
SH367309_VPRO_Lo; //关闭AFE的VPRO烧写,进入正常读AFE模式
改写AFEROM参数后,需要复位后才能生效
SH367309_SHIP_Lo;
delay_1ms(100);
SH367309_SHIP_Hi;
delay_1ms(100);
}
}*/
twi.h
#ifndef _TWI_H_
#define _TWI_H_
#include "head.h"
#define TWI_CLK_HIGH gpio_bit_set(GPIOB, GPIO_PIN_8)
#define TWI_CLK_LOW gpio_bit_reset(GPIOB, GPIO_PIN_8)
#define TWI_DAT_HIGH gpio_bit_set(GPIOB, GPIO_PIN_9)
#define TWI_DAT_LOW gpio_bit_reset(GPIOB, GPIO_PIN_9)
#define TWI_CLK_OUT gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8) //时钟口设置为输出
#define TWI_DAT_OUT gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9) //数据口设置为输出
#define TWI_CLK_IN gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_8) //时钟口设置为输入
#define TWI_DAT_IN gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_9) //数据口设置为输入
#define TWI_RD_CLK gpio_input_bit_get(GPIOB,GPIO_PIN_8)
#define TWI_RD_DAT gpio_input_bit_get(GPIOB,GPIO_PIN_9)
void TWI_Init(void);
void Delay4us(void); //4uS
void TwiStart(void);
void TwiReStart(void);
void TwiStop(void);
unsigned char TwiChkClkRelease(void);
unsigned char TwiSendData(unsigned char Data, unsigned char Clk**);
unsigned char TwiGetData(unsigned char Ack**);
unsigned char CRC8cal(unsigned char *p, unsigned char Length); //look-up table calculte CRC
unsigned char TwiWrite(unsigned char SlaveID, unsigned int WrAddr, unsigned char Length, unsigned char *WrBuf);
unsigned char TwiRead(unsigned char SlaveID, unsigned int RdAddr, unsigned char Length, unsigned char *RdBuf);
void InitTwi(void);
#endif
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_61973119/article/details/136398204
|
|