#include "bsp_iic.h"
/*定制*/
static const _i2c_port_t g_i2c_port[I2C_ID_NUMS] = {
[I2C_ID1] = {
.SCL = {I2C1_PORT_SCL, I2C1_PIN_SCL},
.SDA= {I2C1_PORT_SDA, I2C1_PIN_SDA}
},
[I2C_ID2] = {
.SCL = {I2C2_PORT_SCL, I2C2_PIN_SCL},
.SDA= {I2C2_PORT_SDA, I2C2_PIN_SDA}
}
};
i2c_t g_i2c[I2C_ID_NUMS] = {
[I2C_ID1] = {
.id = I2C_ID1,
.pport = &g_i2c_port[I2C_ID1]
},
[I2C_ID2] = {
.id = I2C_ID2,
.pport = &g_i2c_port[I2C_ID2]
}
};
void bsp_i2c_open(uint8_t id)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
i2c_t *pdev = &g_i2c[id];
if (pdev->flags) {
return;
}
GPIO_InitStruct.Pin = pdev->pport->SCL.pin;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(pdev->pport->SCL.port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = pdev->pport->SDA.pin;
HAL_GPIO_Init(pdev->pport->SDA.port, &GPIO_InitStruct);
HAL_GPIO_WritePin(pdev->pport->SCL.port, pdev->pport->SCL.pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(pdev->pport->SDA.port, pdev->pport->SDA.pin, GPIO_PIN_RESET);
pdev->flags = 1;
}
void bsp_i2c_init(void)
{
//自带AT24
i2c_t *pdev = &g_i2c[I2C_ID1];
pdev->flags = 0;
bsp_i2c_open(I2C_ID1);
//FLOW
pdev = &g_i2c[I2C_ID2];
pdev->flags = 0;
bsp_i2c_open(I2C_ID2);
}
void system_delay_us(int delay)
{
uint16_t differ = 0xffff-delay-5;
//设置定时器2的计数初始值
__HAL_TIM_SetCounter(&htim14,differ);
//开启定时器
HAL_TIM_Base_Start(&htim14);
//不断的获得当前的计数值,由于是不断递增的,当计数值到达最大值时退出循环
while( differ<0xffff-5)
{
differ = __HAL_TIM_GetCounter(&htim14);
};
//关闭定时器
HAL_TIM_Base_Stop(&htim14);
}
/*通用*/
/*
** desc: start I2C bus,act as a "start" signal, a high-to-low transition on the SDA while the SCL is high.
*/
void i2c_start(i2c_t *pdev, uint8_t delay)
{
const struct _io_map *SCL = &pdev->pport->SCL;
const struct _io_map *SDA = &pdev->pport->SDA;
SET_H(SDA);
system_delay_us(delay);
SET_H(SCL);
system_delay_us(delay);
SET_L(SDA);
system_delay_us(delay*2);
SET_L(SCL);
system_delay_us(delay);
}
/*
** desc: stop I2C bus,act as a "stop" signal,a low-to-high transition on the SDA while the SCL is high.
*/
void i2c_stop(i2c_t *pdev,uint8_t delay)
{
const struct _io_map *SCL = &pdev->pport->SCL;
const struct _io_map *SDA = &pdev->pport->SDA;
SET_L(SDA);
system_delay_us(delay);
SET_H(SCL);
system_delay_us(delay*2);
SET_H(SDA);
system_delay_us(delay);
}
/*
** desc: config specified IO input or output mode.
*/
void ioconfig(const struct _io_map *pio, uint8_t sw)
{
GPIO_InitTypeDef GPIO_InitStructure={0};
GPIO_InitStructure.Pin = pio->pin;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Mode = (sw == DEF_OUT)? GPIO_MODE_OUTPUT_PP: GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(pio->port, &GPIO_InitStructure);
}
/*
** desc:check ack bit send by slave after each byte was sent, Each byte of eight bits is followed by one ACK bit.
*/
uint8_t i2c_checkAck(i2c_t *pdev,uint8_t delay)
{
uint8_t ret = I2C_ACK;
const struct _io_map *SCL = &pdev->pport->SCL;
const struct _io_map *SDA = &pdev->pport->SDA;
/* set sda input mode */
ioconfig(SDA,DEF_IN);
SET_H(SCL);
system_delay_us(delay);
if (i2c_rddat(SDA)) {
ret = I2C_NACK;
}
/* set sda output mode */
ioconfig(SDA,DEF_OUT);
SET_L(SCL);
system_delay_us(delay);
return ret;
}
uint8_t i2c_sendbyte(i2c_t *pdev,uint8_t byte,uint8_t delay)
{
uint8_t i;
const struct _io_map *SCL = &pdev->pport->SCL;
const struct _io_map *SDA = &pdev->pport->SDA;
SET_L(SCL);
for (i=0; i<8; i++) {
if ((byte << i ) & 0x80) {
SET_H(SDA);
}
else {
SET_L(SDA);
}
system_delay_us(delay);
SET_H(SCL);
system_delay_us(delay);
SET_L(SCL);
}
SET_L(SDA);
SET_L(SCL);
system_delay_us(delay);
/* receive correct ACK */
return 1;
}
void i2c_SendACK(i2c_t *pdev,uint8_t ack,uint8_t delay)
{
const struct _io_map *SCL = &pdev->pport->SCL;
const struct _io_map *SDA = &pdev->pport->SDA;
if(ack) SET_H(SDA);
else SET_L(SDA);
SET_H(SCL);
system_delay_us(delay);
SET_L(SCL);
system_delay_us(delay);
}
uint8_t i2c_readbyte(i2c_t *pdev, uint8_t delay)
{
uint8_t ret=0,i;
const struct _io_map *SCL = &pdev->pport->SCL;
const struct _io_map *SDA = &pdev->pport->SDA;
/* set sda input mode */
ioconfig(SDA,DEF_IN);
system_delay_us(delay);
for(i=0;i<8;i++) {
SET_H(SCL);
system_delay_us(delay);
ret<<=1;
if(i2c_rddat(SDA))
ret++;
SET_L(SCL);
system_delay_us(delay*2);
}
ioconfig(SDA, DEF_OUT);
return ret;
}
void i2c_setscllow(i2c_t *pdev)
{
const struct _io_map *SCL = &pdev->pport->SCL;
SET_L(SCL);
}
void i2c_setsclhigh(i2c_t *pdev)
{
const struct _io_map *SCL = &pdev->pport->SCL;
SET_H(SCL);
}