打印
[电池电源管理]

SH367309代码简介(3)

[复制链接]
1327|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-6-27 09:01 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
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

使用特权

评论回复
沙发
药无尘| | 2024-6-28 13:52 | 只看该作者
这就是模拟方式实现了吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2028

主题

15903

帖子

13

粉丝