下面是我用寄存器写的读写GT9系列IC的代码。在读数据上还不能连续读取,只能一个地址一个数据的读,请各位大哥指正。
//////////////////////////////////////////////////////i2c_hard.c
#include "i2c_hard.h"
void I2C_Init(void)
{
////////////////I2C GPIO重映像
RCC->APB2ENR |= 1<<0; //使能AFIO时钟
AFIO->MAPR |= 1<<1; //控制I2C1的SCL和SDA复用功能在GPIO端口的映像 SCL/PB8,SDA/PB9
////////////////I2C GPIO配置
RCC->APB2ENR |= 1<<3; //使能PORTB时钟
GPIOB->CRH &= 0xFFFFFF00; //I2C1:PB8->SCL, PB9->SDL
GPIOB->CRH |= 0x000000FF; //复用开漏输出
//GPIOB->CRL &= 0x00FFFFFF; //I2C1:PB6->SCL, PB7->SDL
//GPIOB->CRL |= 0xFF000000; //复用开漏输出
////////////////I2C 寄存器配置
RCC->APB1ENR |= 1<<21; //使能外设I2C1时钟
RCC->APB1RSTR |= 1<<21; //复位I2C1
RCC->APB1RSTR &= ~(1<<21); //复位结束I2C1
I2C1->CR2 |= 36; //000010:2MHz ... 100100:36MHz,其他禁用(此处为36MHZ)
I2C1->CCR |= 0<<15; //I2C主模式 0:标准模式的I2C 1:快速模式的I2C
I2C1->CCR |= 90<<0; //时钟控制分频系数 = PCLK1/2/f(f为想得到的频率,此处PCLK1=36MHZ,f=200KHZ)
I2C1->TRISE |= 37; //最大允许SCL上升时间为1000ns,故TRISE[5:0]中必须写入(1000ns/(1000/36)ns = 36+1)
I2C1->CR1 |= 1<<10; //打开ACK应答,在接收到一个字节后返回一个应答
I2C1->CR1 |= 1<<6; //广播呼叫使能
I2C1->OAR1 |= 0<<15; //寻址模式 1 响应10位地址 0 响应7位地址
I2C1->OAR1 |= 1<<14; //必须始终由软件保持为 1
I2C1->OAR1 |= INTERFACE_ADDR<<1;//设置接口地址的 7~1位(接口地址设为0X30)
I2C1->CR2 |= 1<<9; //事件中断使能
I2C1->CR2 |= 1<<8; //出错中断使能
I2C1->CR1 |= 1<<0; //开启I2C1
}
void I2C_Start(void) //I2C1产生起始条件
{
I2C1->CR1 |= 1<<8;
}
void I2C_Stop(void) //I2C1产生停止条件
{
I2C1->CR1 |= 1<<9;
}
void I2C_End(void) //关闭I2C
{
I2C1->CR1 &= ~(1<<0);
}
void I2C_Write_U8(u8 data) //I2C1写一个字节
{
I2C1->DR = data;
}
u8 I2C_Read_U8(void) //I2C1读一个字节
{
while(!RXNE_STATUS); //接收到数据标志位
return I2C1->DR;
}
u8 I2C_Write(u16 addr, u8* data, u16 length)
{
u16 clear = 0;
u8 addr_l=0, addr_h=0;
u16 send_loop;
addr_h = (u8)(addr>>8);
addr_l = (u8)(addr&0x00FF);
I2C_Start();
while(!SB_STATUS);
I2C_Write_U8(WRITE_ADDR);
while(!ADDR_STATUS);
clear = I2C1->SR1;
clear = I2C1->SR2;
I2C_Write_U8(addr_h);
while(!BTF_STATUS);
I2C_Write_U8(addr_l);
for(send_loop=0;send_loop<length;send_loop++)
{
while(!BTF_STATUS);
I2C_Write_U8(*data);
data++;
}
I2C_Stop();
return 0;
}
u8* I2C_Read(u16 addr, u8* data, u16 length)
{
u16 clear = 0;
u8 addr_l=0, addr_h=0;
u16 send_loop;
for(send_loop=0;send_loop<length;send_loop++)
{
addr_h = (u8)(addr>>8);
addr_l = (u8)(addr&0x00FF);
I2C_Start();
while(!SB_STATUS);
I2C_Write_U8(WRITE_ADDR);
while(!ADDR_STATUS);
clear = I2C1->SR2;
I2C_Write_U8(addr_h);
while(!BTF_STATUS);
I2C_Write_U8(addr_l);
I2C_Start();
while(!SB_STATUS);
I2C_Write_U8(READ_ADDR);
while(!ADDR_STATUS);
clear = I2C1->SR2;
while(!BTF_STATUS);
clear = I2C1->SR1;
*data = I2C_Read_U8();
data++;
addr++;
I2C_Stop();
}
return data;
}
//////////////////////////////////////////////////////i2c_hard.h
#ifndef __I2C_HARD_H
#define __I2C_HARD_H
#include "sys.h"
#include "led.h"
#include "delay.h"
#define WRITE_ADDR 0x28 //从设备(GT9)写数据地址
#define READ_ADDR 0x29 //从设备(GT9)读数据地址
#define INTERFACE_ADDR 0x30 //自身地址
#define SB_STATUS (I2C1->SR1 & 1<<0) //起始位(主模式)
#define ADDR_STATUS (I2C1->SR1 & 1<<1)//地址已被发送(主模式)
#define BTF_STATUS (I2C1->SR1 & 1<<2)//字节发送结束
#define RXNE_STATUS (I2C1->SR1 & 1<<6)//数据寄存器非空(接收时)
void I2C_Init(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_End(void);
void I2C_Write_U8(u8 data);
u8 I2C_Read_U8(void);
u8 I2C_Write(u16 addr, u8* data, u16 length);
u8* I2C_Read(u16 addr, u8* data, u16 length);
#endif
|