基于I2C的stm32f103c8t6的硬件配置(寄存器实现)
前面已经学过了通过两个IO口模拟I2C的通信,这种方法可以在硬件资源少的时候很方便的进行各个外设之间的通信,但在模拟时序的精度上还是不如硬件I2C的,因为硬件I2C是通过硬件自动生成的,精度高,同时在传输速率上硬件I2C也比软件I2C的传输速率要快,因此我们可以得出硬件I2C在刚需高性能,高稳定的场景下使用。
I2C的初始化
在前面我们已经介绍了I2C的寄存器,在初始化中我们需要打开具有硬件I2C的引脚的时钟,然后进行GPIO的配置,配置成复用开漏模式,配置完成这些后我们还需要对 SMBUS和FS进行配置,SMBUS是配置I2C的CR1寄存器中的一位,主要是用来选择是否选择I2C模式,而FS是CCR寄存器中的一位,用来选择I2C的模式,一般我们统一都是配置成标准模式,接下来就是配置时钟CR2外设时钟频率,也就是36MHZ,也就是挂载到APB1总线上的,然后就是通信速率CCR,它的值是根据CR2来的。
SCL频率 = 36,000,000 Hz / (2 * 180) = 36,000,000 / 360 = 100,000 Hz = 100kHz
接着就是最大上升时间TRISE,具体的计算方法为
TRISE值 = (最大允许上升时间 / APB1时钟周期) + 1
具体的代码实现:
void I2C_INIT()
{RCC->APB2ENR|=RCC_APB2ENR_IOPBEN;GPIOB->CRL &=~GPIO_CRL_CNF7|GPIO_CRL_MODE7|GPIO_CRL_CNF6|GPIO_CRL_MODE6;GPIOB->CRL |=GPIO_CRL_MODE6|GPIO_CRL_MODE7;GPIOB->CRL |=GPIO_CRL_CNF7|GPIO_CRL_CNF6;I2C1->CR1 &=~I2C_CR1_SMBUS;I2C1->CCR &=~I2C_CCR_FS;I2C1->CR2 =36;I2C1->CCR=180;I2C1->TRISE=37;I2C1->CR1 |=I2C_CR1_PE;}
I2C的开始信号和停止信号
I2C硬件发送开始信号然后等待应答在应答期间我们需要有一个变量来进行检测超时,不然程序就会一直卡死。
uint8_t I2C_START()
{I2C1->CR1 |=I2C_CR1_START;uint16_t timeout=0xffff;while(I2C1->CR1&I2C_CR1_ACK&&timeout){timeout--;}return timeout?OK:NOOK;}
停止信号直接用硬件停止即可
void I2C_ACK()
{I2C1->CR1 |=I2C_CR1_ACK;}
I2C的应答信号和非应答信号
应答信号ACK存于CR1中的一位
void I2C_STOP()
{I2C1->CR1 |=I2C_CR1_STOP;}
非应答信号直接置0即可
void I2C_NACK()
{I2C1->CR1 &=~I2C_CR1_ACK;}
发送地址
在开始传输数据之前我们要选择是哪个从机设备想要和主机进行通信,因此我们就写入一个想要进行通信的从机的地址然后写入寄存器DR最后判断是否写入成功,主要就是进行地址的写入,用来告诉主机是哪个从机想要进行通信,写入完成后我们要进行清除,清除的做法就是读取寄存器SR2。
uint8_t I2C_SendAddr(uint8_t addr)
{uint16_t timeout=0xfff;I2C1->DR=addr;while(I2C1->SR1&I2C_SR1_ADDR&timeout){timeout--;}if(timeout>0){I2C1->SR2;}return timeout?OK:NOOK;}
发送数据
发送数据前先检测发送寄存器是否为空,为空后写入数据寄存器DR,然后接着判断BTF位。BTF是位于SR1寄存器中的关于数据是否发完成的位。
uint8_t I2C_Sendbyte(uint8_t byte)
{uint16_t timeout=0xffff;while(I2C1->SR1&I2C_SR1_TXE&&timeout){timeout--;}I2C1->DR=byte;timeout=0xffff;while(I2C1->SR1&I2C_SR1_BTF&timeout){timeout--;}return timeout?OK:NOOK;}
读取数据
读取数据就是判断RXNE是否是满的,是满的就直接返回数据寄存器DR。
uint8_t I2C_Readbyte()
{uint16_t timeout=0xffff;while(I2C1->SR1&I2C_SR1_RXNE&timeout){timeout--;}return timeout?I2C1->DR:NOOK;}
以上就是关于I2C中硬件寄存器的配置,如果有错误的地方还请广大网友多多指正。