include <stdio.h>

include <stm32f10x.h>

int fputc(int ch, FILE *fp)
{

if (fp == stdout)
{
    if (ch == '\n')
    {
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, '\r');
    }
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    USART_SendData(USART1, ch);
}
return ch;

}

// 发送开始信号和从机地址(传输模式)
void start(void)
{

if (I2C1->SR1 || I2C1->SR2)
    printf("error!\n");

restart:

I2C_GenerateSTART(I2C1, ENABLE);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) == ERROR); // 等待开始信号发送完毕
I2C_SendData(I2C1, 0xa0); // 从机地址(传输模式)
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == ERROR) // 等待从机确认
{
    if (I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET)
    {
        // 若从机未响应, 则重试
        // 执行了写操作后需要等待一段时间才能执行其他命令
        I2C_ClearFlag(I2C1, I2C_FLAG_AF);
        //printf("NACK!\n");
        goto restart;
    }
}

}

uint8_t read(uint8_t addr)
{

start();
I2C_SendData(I2C1, addr); // 发送存储器地址
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR);

I2C_GenerateSTART(I2C1, ENABLE); // RESTART
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
I2C_SendData(I2C1, 0xa1); // 从机地址(接收模式)
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == ERROR);

I2C_GenerateSTOP(I2C1,ENABLE); // 接收最后一字节数据前先准备好STOP信号
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) == ERROR); // 等待数据接收完毕
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET); // 等待停止信号发送完毕
return I2C_ReceiveData(I2C1);

}

void write(uint8_t addr, uint8_t value)
{

start();
I2C_SendData(I2C1, addr); // 前两个数据可连发, 无需等待TXE置位
I2C_SendData(I2C1, value);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR); // 等待数据完全发送完毕
I2C_GenerateSTOP(I2C1,ENABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET); // 等待停止信号发送完毕

}

void read_more(uint8_t addr, char *data, uint8_t len)
{

start();
I2C_SendData(I2C1, addr);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR);

I2C_GenerateSTART(I2C1, ENABLE);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
I2C_SendData(I2C1, 0xa1);
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == ERROR);

I2C_AcknowledgeConfig(I2C1, ENABLE);
while (len--)
{
    if (len == 0)
    {
        I2C_AcknowledgeConfig(I2C1, DISABLE);
        I2C_GenerateSTOP(I2C1,ENABLE); // 接收最后一字节数据前先准备好STOP信号
    }
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) == ERROR); // 等待当前数据接收完毕
    *data++ = I2C_ReceiveData(I2C1);
}
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET); // 等待停止信号发送完毕

}

void write_more(uint8_t addr, const char *data, uint8_t len)
{

start();
I2C_SendData(I2C1, addr);
while (len--)
{
    I2C_SendData(I2C1, *data++);
    while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) == ERROR); // 等待TXE
}
while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR); // 等待全部数据发送完毕
I2C_GenerateSTOP(I2C1,ENABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET); // 等待停止信号发送完毕

}

int main(void)
{

char str[20];
GPIO_InitTypeDef gpio;
I2C_InitTypeDef i2c;
USART_InitTypeDef usart;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1, ENABLE);

// 串口发送引脚设为复用推挽输出
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_9;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio);

// I2C引脚设为复用开漏输出
gpio.GPIO_Mode = GPIO_Mode_AF_OD;
gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Init(GPIOB, &gpio);

USART_StructInit(&usart);
usart.USART_BaudRate = 115200;
usart.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &usart);
USART_Cmd(USART1, ENABLE);

I2C_StructInit(&i2c);
i2c.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &i2c);
I2C_Cmd(I2C1, ENABLE);

write(17, 0x31);
printf("read: 0x%02x\n", read(17));

write_more(17, "Hello!", 7); // 区域16~23
read_more(17, str, sizeof(str));
printf("str: %s\n", str);

write_more(8, "12345678ABCDEFG", 16); // 先将前8个字符写入地址8~15处, 然后回到地址8处写入剩下的字符, 包括最后的\0
read_more(8, str, sizeof(str));
printf("str: %s\n", str);

printf("I2C1->SR1=0x%04x, I2C1->SR2=0x%04x\n", I2C_ReadRegister(I2C1, I2C_Register_SR1), I2C_ReadRegister(I2C1, I2C_Register_SR2));
while (1)
    __WFI();

}
【程序运行结果1】
read: 0x31
str: Hello!
str: ABCDEFG
I2C1->SR1=0x0000, I2C1->SR2=0x0000
两个SR寄存器的值都为0表明I2C正常工作。

标签: none

评论已关闭