shuichan_old/STM32F103_App1/HardWare/IIC/iic.c

149 lines
3.1 KiB
C
Raw Normal View History

#include "iic.h"
/* Software I2C delay (microseconds), based on SysTick */
static void delayUs(uint16_t us)
{
uint32_t start = SysTick->VAL;
uint32_t ticks = us * (SystemCoreClock / 1000000);
if (start < ticks) {
while (SysTick->VAL > start);
while (SysTick->VAL < (SysTick->LOAD - (ticks - start)));
} else {
while ((SysTick->VAL < start) && (SysTick->VAL >= (start - ticks)));
}
}
/* I2C Interface Initialization */
void iicInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
/* SDA - PA12, open-drain output */
GPIO_InitStruct.Pin = SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
/* SCL - PA11, push-pull output */
GPIO_InitStruct.Pin = SCL_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
IIC_SCL_H;
IIC_SDA_H;
/* <20><><EFBFBD>߻ָ<DFBB><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I2C <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;<EFBFBD><CDBE><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>¼/<2F><><EFBFBD>Ź<EFBFBD>/OTA <20><>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>
* EEPROM <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> SDA <EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>º<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>ſ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> SDA <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 9 <EFBFBD><EFBFBD> SCL ʱ<EFBFBD>ӰѴӻ<EFBFBD><EFBFBD>ĵ<EFBFBD>ǰ<EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٷ<EFBFBD> STOP <EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
if (READ_SDA == 0) {
for (int i = 0; i < 9; i++) {
IIC_SCL_L;
delayUs(5);
IIC_SCL_H;
delayUs(5);
}
iicStop();
}
}
/* I2C Start Signal */
void iicStart(void)
{
IIC_SDA_H;
IIC_SCL_H;
delayUs(4);
IIC_SDA_L; /* SCL high, SDA high->low = start */
}
/* I2C Stop Signal */
void iicStop(void)
{
IIC_SDA_L;
IIC_SCL_H;
delayUs(4);
IIC_SDA_H; /* SCL high, SDA low->high = stop */
}
/* Wait for ACK: returns 0=OK, 1=timeout */
uint8_t iicWaitAck(void)
{
unsigned char timeout = 0;
IIC_SDA_H;
IIC_SCL_H;
while (READ_SDA) {
timeout++;
if (timeout > 250) {
iicStop();
return 1;
}
delayUs(2);
}
IIC_SCL_L;
delayUs(20);
return 0;
}
/* Send One Byte (MSB first), return ACK status: 0=ACK, 1=NACK/timeout */
uint8_t iicSendByteAck(uint8_t txd)
{
unsigned char t;
IIC_SCL_L;
for (t = 0; t < 8; t++) {
IIC_SDA_OUT(((txd & 0x80) >> 7));
txd <<= 1;
delayUs(2);
IIC_SCL_H;
delayUs(2);
IIC_SCL_L;
}
return iicWaitAck();
}
/* Send One Byte (MSB first), legacy API without ACK return */
void iicSendByte(uint8_t txd)
{
(void)iicSendByteAck(txd);
}
/* Read One Byte; ack=1 send ACK, ack=0 send NACK */
unsigned char iicReadByte(uint8_t ack)
{
unsigned char i;
unsigned char receive = 0;
IIC_SCL_L;
delayUs(20);
for (i = 0; i < 8; i++) {
IIC_SCL_H;
delayUs(20);
receive <<= 1;
if (READ_SDA) receive++;
delayUs(20);
IIC_SCL_L;
delayUs(20);
}
if (!ack) {
/* NACK */
IIC_SDA_H;
IIC_SCL_H;
delayUs(2);
IIC_SCL_L;
} else {
/* ACK */
IIC_SDA_L;
IIC_SCL_H;
delayUs(2);
IIC_SCL_L;
IIC_SDA_H;
}
return receive;
}