Created
May 3, 2022 13:21
-
-
Save Franky1/47d496c2b25dbdef2b259d573a8c8458 to your computer and use it in GitHub Desktop.
bq2022A example reading library for STM32 or other MCUs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdbool.h> | |
#include <stm32f0xx_ll_gpio.h> | |
const int tRST = 600; | |
const int tPPD = 40; | |
const int tPPmin = 60; | |
const int tRSTREC = 480; | |
const int tWSTRB = 7; | |
const int tWDH = 90; | |
const int tREC = 5; | |
const int tRSTRB = 7; | |
const int tODD = 13; | |
const int tODHO = 60; | |
const uint8_t cReadROM = 0x33; | |
const uint8_t cSkipROM = 0xCC; | |
const uint8_t cReadMemoryCRC = 0xC3; | |
#define GPIO_PORT GPIOA | |
#define GPIO_PIN LL_GPIO_PIN_1 | |
static void BusyDelayMicroseconds(int us) { | |
// Overwrite your delay here; must be precise | |
while (us--) { | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
__ASM("NOP"); | |
} | |
} | |
static uint8_t CRC8(uint8_t * ptr, int len) { | |
uint8_t result = 0; | |
while (len--) { | |
result ^= * ptr++; | |
for (uint8_t i = 0; i < 8; i++) { | |
if (result & 0x01) | |
result = (result >> 1) ^ 0x8C; | |
else | |
result >>= 1; | |
} | |
} | |
return result; | |
} | |
void Init() { | |
LL_GPIO_InitTypeDef GPIO_InitStruct; | |
GPIO_InitStruct.Pin = GPIO_PIN; | |
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; | |
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; | |
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; | |
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; | |
LL_GPIO_Init(GPIO_PORT, & GPIO_InitStruct); | |
} | |
static void Output(bool high) { | |
LL_GPIO_SetPinMode(GPIO_PORT, GPIO_PIN, LL_GPIO_MODE_OUTPUT); | |
if (high) | |
LL_GPIO_SetOutputPin(GPIO_PORT, GPIO_PIN); | |
else | |
LL_GPIO_ResetOutputPin(GPIO_PORT, GPIO_PIN); | |
} | |
static bool Input() { | |
LL_GPIO_SetPinMode(GPIO_PORT, GPIO_PIN, LL_GPIO_MODE_INPUT); | |
return (bool) LL_GPIO_IsInputPinSet(GPIO_PORT, GPIO_PIN); | |
} | |
static void Release() { | |
LL_GPIO_SetPinMode(GPIO_PORT, GPIO_PIN, LL_GPIO_MODE_ANALOG); | |
} | |
static void WriteBit(bool bit) { | |
Output(false); | |
BusyDelayMicroseconds(tWSTRB); | |
if (bit) | |
Output(true); | |
BusyDelayMicroseconds(tWDH - tWSTRB); | |
Output(true); | |
BusyDelayMicroseconds(tREC); | |
} | |
static bool ReadBit() { | |
Output(false); | |
BusyDelayMicroseconds(tRSTRB); | |
Release(); | |
BusyDelayMicroseconds(tODD); | |
bool result = Input(); | |
BusyDelayMicroseconds(tREC + tODHO - tODD); | |
return result; | |
} | |
static void WriteByte(uint8_t x) { | |
for (int i = 0; i < 8; i++) { | |
bool val = x & (1 << i); | |
WriteBit(val); | |
} | |
} | |
static uint8_t ReadByte() { | |
uint8_t result = 0; | |
for (int i = 0; i < 8; i++) { | |
bool val = ReadBit(); | |
result |= (val << i); | |
} | |
return result; | |
} | |
ErrorStatus Reset() { | |
// Hard reset | |
Output(false); | |
BusyDelayMicroseconds(5000); | |
Release(); | |
BusyDelayMicroseconds(5); | |
// Detect if the pin is pulled down unexpectedly | |
if (!Input()) | |
return ERROR; | |
Output(true); | |
BusyDelayMicroseconds(100); | |
Output(false); | |
BusyDelayMicroseconds(tRST); | |
Output(true); | |
BusyDelayMicroseconds(tPPD); | |
Release(); | |
BusyDelayMicroseconds(tPPmin); | |
// If input is low then chip is present | |
bool presence = !Input(); | |
Output(true); | |
if (presence) | |
BusyDelayMicroseconds(tRSTREC - tPPmin - tPPD); | |
return presence ? SUCCESS : ERROR; | |
} | |
ErrorStatus ReadROM(uint8_t * buf) { | |
if (Reset() == ERROR) | |
return ERROR; | |
WriteByte(cReadROM); | |
const int len = 7; | |
for (int i = 0; i < len; i++) { | |
buf[i] = ReadByte(); | |
} | |
uint8_t crc = ReadByte(); | |
if (crc != CRC8(buf, len)) | |
return ERROR; | |
return SUCCESS; | |
} | |
// page: 0-3 | |
ErrorStatus ReadEPROM(uint8_t page, uint8_t * buf) { | |
if (Reset() == ERROR) | |
return ERROR; | |
WriteByte(cSkipROM); | |
uint8_t cmd[3]; | |
cmd[0] = cReadMemoryCRC; | |
cmd[1] = 0x20 * page; | |
cmd[2] = 0; | |
for(int i = 0; i < 3; i++) | |
WriteByte(cmd[i]); | |
uint8_t crc1 = ReadByte(); | |
if (CRC8(cmd, 3) != crc1) | |
return ERROR; | |
const int size = 32; | |
for (int i = 0; i < size; i++) { | |
buf[i] = ReadByte(); | |
} | |
uint8_t crc2 = ReadByte(); | |
if (CRC8(buf, size) != crc2) | |
return ERROR; | |
return SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment