一、配置i2c设备
1)在终端中操作,输入指令
sudo raspi-config
2)然后会出现设置界面,然后跟着如下图片操作
第一项:Change User Password: 更改用户登录密码,也就是登录树莓派的raspberry 密码。点击进入就可以设置新的登陆密码。
第二项:Network Options : 网络设置, 打开这个设置后可以连接wifi,设置机器名称 ,接口启用禁止等
第三项:Boot Options : 启动时选择进入的环境(命令模式/图形化模式)
**第四项:Localisation Options :**本地化设置包含:language语言设 置/Timezone时区设置/Keyboard键盘布局/wifi country 无线wif国家设置。
第五项:Interfacing Options : 系统功能设置,包含Camera摄像头启用 / SSH启用/VNC启用/SPI启用/I2C启用/serial启用/wire/GPIO 需要用到哪些就开启哪些功能
第六项:Overclock : 超频会减少树莓派使用寿命,正常情况下不建议超频使用。
第七项: Advanced Options : 高级设置,包含扩展TF卡使用空间/显示器overscan’设置/memorySplit设置/Audio音频输出设置/分辨率设置/等等
**第八项:Update :**系统更新,用于升级更新系统
第九项:About raspi-cofnig : 关于设置的系统
最后选择“是”
3)i2c总线扫描
通过i2cdetect -l指令可以查看树莓派上的I2C总线,从返回的结果来看树莓派含有两个I2C总线,通过阅读相关的资料,树莓派1代使用I2C0,而树莓派2代使用I2C1。
pi@raspberrypi:~/wiringPi $ i2cdetect -l
i2c-1 i2c bcm2835 I2C adapter I2C adapter
4)i2c设备查询
若总线上挂载I2C从设备,可通过i2cdetect扫描某个I2C总线上的所有设备。
i2cdetect -y 1
我挂在i2c总线上的是stm32的硬件i2c,从机地址设置为0x50(即0x28<<1)
二、通信代码指令
1、树莓派4b调用wiringPi库
#include "stdio.h"
#include "wiringPi.h"
#include "wiringPiI2C.h"
#include "pthread.h"
#include "unistd.h"
void *pthread_fun(void *arg)
{
int fd = *((int*)arg);
int Tx_buf = 12;
while(1)
{
wiringPiI2CWrite(fd, Tx_buf);
sleep(1);
}
return NULL;
}
int main(int argc, char *argv[])
{
int fd, err;
int Rx_buf;
pthread_t tid;
//对wiringPi初始化
if(wiringPiSetup() != 0)
{
printf("wiringPi error!\n");
return -1;
}
//指定i2c从机设备,并初始化i2c
fd = wiringPiI2CSetup(0x28);
if(fd < 0)
{
printf("wiringPiI2CSetup error!\n");
return fd;
}
err = pthread_create(&tid, NULL, pthread_fun, &fd);
if(err != 0)
{
printf("create pthread error\n");
return -2;
}
while(1)
{
Rx_buf = 0;
//读取数据
Rx_buf = wiringPiI2CRead(fd);
//判断是否读取成功
if(Rx_buf != 0)
printf("Temperature is %d ℃\n", Rx_buf);
sleep(1);
}
return 0;
}
2、STM32F103硬件i2c代码
/*********************************************************************************************************
* 模块名称: iic.c
* 摘 要: 硬件IIC从机实验
* 当前版本: 1.0.0
* 作 者: 杨
* 完成日期: 2019年4月19日
* 内 容:
* 注 意:
**********************************************************************************************************
* 取代版本:
* 作 者:
* 完成日期:
* 修改内容:
* 修改文件:
*********************************************************************************************************/
/*********************************************************************************************************
* 包含头文件
*********************************************************************************************************/
#include "iic.h"
/*********************************************************************************************************
* 宏定义
*********************************************************************************************************/
/*********************************************************************************************************
* 内部变量
*********************************************************************************************************/
u8 IIC1_Rx_Buff = 0;
u8 IIC1_Tx_Buff = 67;
//#define SIZE2 sizeof(IIC1_Tx_Buff)
uint32_t state;
/*********************************************************************************************************
* 内部函数声明
*********************************************************************************************************/
/*********************************************************************************************************
* 内部函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称:
* 函数功能:
* 输入参数:
* 输出参数:
* 返 回 值:
* 创建日期:
* 注 意:
*********************************************************************************************************/
/*********************************************************************************************************
* API函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称: InitI2C1
* 函数功能: 初始化I2C1
* 输入参数: void
* 输出参数: void
* 返 回 值: void
* 创建日期: 2019年4月21日
* 注 意: PB6:SCL; PB7:SDA
*********************************************************************************************************/
void InitI2C1(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
I2C_InitTypeDef I2C_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
//GPIO配置
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; //设置为复用开漏输出,实现iic的线与逻辑
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
//I2C1配置
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; //使能ack
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //7位设备地址
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;//占空比为1/2
I2C_InitStruct.I2C_ClockSpeed = 100000; //时钟频率为100k
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_OwnAddress1 = 0x50; //设置硬件从机地址
I2C_Init(I2C1, &I2C_InitStruct);
//NVIC配置
NVIC_InitStruct.NVIC_IRQChannel = I2C1_EV_IRQn; //事件中断
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = I2C1_ER_IRQn; //错误中断
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStruct);
I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_ERR | I2C_IT_BUF, ENABLE);
I2C_Cmd(I2C1, ENABLE);
}
/*********************************************************************************************************
* 函数名称: I2C1_EV_IRQHandler
* 函数功能: I2C1事件中断服务函数
* 输入参数: void
* 输出参数: void
* 返 回 值: void
* 创建日期: 2019年4月21日
* 注 意:
*********************************************************************************************************/
void I2C1_EV_IRQHandler(void)
{
//static u8 s_iRdata;
//static u8 s_iTdata;
state = I2C_GetLastEvent(I2C1);
switch(state)
{
//EV1(receive)(从机匹配地址成功)
case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
I2C_ReadRegister(I2C1, I2C_Register_SR1); //读取SR1
I2C_ReadRegister(I2C1, I2C_Register_SR2); //读取SR2后,硬件自动将SR1->ADDR清零
//s_iRdata = 0;
break;
//EV2(Byte received)
case I2C_EVENT_SLAVE_BYTE_RECEIVED:
IIC1_Rx_Buff = I2C_ReceiveData(I2C1);//读取DR寄存器硬件将自动将SR1->RxNE清零
//IIC1_Rx_Buff[s_iRdata] = I2C_ReceiveData(I2C1);//读取DR寄存器硬件将自动将SR1->RxNE清零
//s_iRdata++;
break;
//EV4(stop)
case I2C_EVENT_SLAVE_STOP_DETECTED:
I2C_ReadRegister(I2C1, I2C_Register_SR1); //读取SR1
I2C1->CR1 |= 0x0001; //写CR1->PE为1,启动I2C1
break;
//EV1(transmitter)
case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
I2C_ReadRegister(I2C1, I2C_Register_SR1); //读取SR1
I2C_ReadRegister(I2C1, I2C_Register_SR2); //读取SR2后,硬件自动将SR1->ADDR清零
//s_iTdata = 0;
break;
//EV3、EV3-1(Byte transmit)
case I2C_EVENT_SLAVE_BYTE_TRANSMITTING:
case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:
//I2C_SendData(I2C1, IIC1_Tx_Buff[s_iTdata++]); //写I2C->DR后硬件将自动清除TxE位
I2C_SendData(I2C1, IIC1_Tx_Buff); //写I2C->DR后硬件将自动清除TxE位
break;
//EV3-2
case I2C_EVENT_SLAVE_ACK_FAILURE:
I2C1->SR1 &= 0xFBFF; //写SR1->AF = 0以清除AF位
break;
default:
break;
}
}
/*********************************************************************************************************
* 函数名称: I2C1_ER_IRQHandler
* 函数功能: I2C1错误中断服务函数
* 输入参数: void
* 输出参数: void
* 返 回 值: void
* 创建日期: 2019年4月21日
* 注 意:
*********************************************************************************************************/
void I2C1_ER_IRQHandler(void)
{
if(I2C_GetITStatus(I2C1, I2C_IT_SMBALERT))
{
I2C_ClearITPendingBit(I2C1, I2C_IT_SMBALERT);
}
else if(I2C_GetITStatus(I2C1, I2C_IT_TIMEOUT))
{
I2C_ClearITPendingBit(I2C1, I2C_IT_TIMEOUT);
}
else if(I2C_GetITStatus(I2C1, I2C_IT_PECERR))
{
I2C_ClearITPendingBit(I2C1, I2C_IT_PECERR);
}
else if(I2C_GetITStatus(I2C1, I2C_IT_OVR))
{
I2C_ClearITPendingBit(I2C1, I2C_IT_OVR);
}
else if(I2C_GetITStatus(I2C1, I2C_IT_AF))
{
I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
}
else if(I2C_GetITStatus(I2C1, I2C_IT_ARLO))
{
I2C_ClearITPendingBit(I2C1, I2C_IT_ARLO);
}
else if(I2C_GetITStatus(I2C1, I2C_IT_BERR))
{
I2C_ClearITPendingBit(I2C1, I2C_IT_BERR);
}
I2C1->CR1 |= 0x0001; //启动I2C1
I2C1->SR1 = 0;
I2C1->SR2 = 0;
}
3、编译运行结果
编译
pi@raspberrypi:~/wiringPi $ gcc i2c_wiringPi.c -o i2c_wiringPi -lpthread -lwiringPi
pi@raspberrypi:~/wiringPi $ ./i2c_wiringPi
运行结果