stm32的模拟/硬件的spi和i2c通信及其应用

本章节主要讲解:模拟spi、硬件spi、两种方法驱动6针oled、模拟i2c、硬件i2c、硬件i2c驱动mpu6050

一、硬件spi

1、首先是基础知识,这里参考正点原子的资料:s

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

2、接下来讲一讲硬件spi及cubemx配置方法:

这里在cubemx配置,Mode部分配置是全双工还是半双工还是单线通信,是主机模式还是从机模式,如果是单线,那么是只接受还是只接受

Hardware NSS Signal配置NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制

最下面配置一些参数,包括但不限于数据大小,第一位是MSB位还是LSB位,串行同步时钟的空闲电位状态等等,和谐都可以和前面给出的正点原子的资料对应起来

至于使用的spi复用到哪一组引脚可以在芯片上标记

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

 生成的代码如下:

spi初始化部分

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

spi回调函数部分,在这里配置好端口,注意如果要配置多个spi,那么也只能有一处回调函数。

初始化和回调的代码和正点原子几乎的一样的

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

 正点原子多给了一个速度设置函数和读写字节函数,可以用来和w28q128(flash)通信使用,具体的移植代码这里不放出来了

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

 这里重点看一下hal库的spi初始化代码(在spi初始化里面),这里的形式参数是一个类型别名的结构体变量watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

 这是这个结构体类型对应的成员,是硬件spi的一些基础参数watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

比较特殊的是SPI_TypeDef和SPI_InitTypeDef这两个结构体类型(是嵌套在主结构体类型里面的)

具体用法也不说了,前面的正点原子资料说的很清楚了watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

二、应用:分别用模拟spi和硬件spi驱动6针oled

注意1:模拟spi是利用四个端口来模拟硬件spi,这样的好处是通用型强,不管怎样的32单片机,只要配置四个GPIO就可以。硬件spi的话不同单片机需要有不同的配置(引脚、功能等),通用型相对模拟spi比较低,但是硬件spi的性能比模拟spi强。

注意2:信泰微电子卖的oled有4针(i2c驱动)、6针(spi驱动)、7针(spi/i2c驱动)三种版本,这里用的是6针的。

注意3:模拟spi驱动6针oled不可以使用刷新函数

硬件spi可以使用刷新函数,但中文汉字的具体代码需要修改

1、模拟spi驱动6针oled:

配置好四个端口

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

将端口在这里对应好

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

 然后接线接可以了,scl(时钟)、sda,rst、dc对应着接就可以了

主函数怎么编写代码,怎么用取模软件、怎么去显示动态变量/汉字/图片、每一种oled函数怎么用限于篇幅这里都不说了

 2、硬件spi驱动oled:

配置好spi,这样就有了mosi、miso和sck

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

dc和rst还是得用端口模拟(也得配置一下端口) watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

然后scl—scl,sda—mosi,rst—rst,dc—dc

主函数怎么编写代码也省略了,具体的oled移植代码限于篇幅也省略了


三、模拟i2c

模拟i2c是正点原子提供的,因为stm32的硬件i2c是鸡肋,为了规避版权而弄的很复杂,效率低,所以才使用了模拟i2c,用两个端口来模拟

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

模拟i2c代码部分(.c+.h):

利用这些i2c函数就可以实现一定的操作了

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 


四、硬件i2c

1、cubemx配置:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

2、代码部分:

这里也是和spi差不多,一个初始化去配置基础参数,一个回调函数(被HAL_I2C_Init调用)去配置端口

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16 

 还有一些其他硬件i2c函数,具体的知识可以参考对应系列芯片的st中文参考手册和其他csdn博客,这里博主用的不多,就不展开了


五、应用:用硬件i2c驱动mpu6050

1、配置好硬件i2c,这里省略了

2、将mpu和inv代码移植过来,在mpu6050.h里面对应好I2c结构体和端口初始化函数,要和刚刚配置的i2c对应好。至于mpu6050的移植代码,可以去csdn找,f1/f4/h7等等都是有的。当然了如果单片机比较厉害,自带陀螺仪,那么就不要再去单独买了,直接写代码即可

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDljZPliJst55S15o6nLWh5Yg,size_20,color_FFFFFF,t_70,g_se,x_16

 3、具体的主函数内使用这里也不讲了,这里就是讲讲移植的思路

4、mpu6050也可以用模拟i2c驱动,这里限于篇幅就不展开了

 

  • 1
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
很高兴为您解答这个问题。以下是针对STM32-24位AD7799驱动手册代码详解的简要说明。 首先,AD7799是一款24位精度的模数转换器,可用于测量各种传感器的输出信号。它可通过SPI接口与微控制器(如STM32通信,以读取和写入寄存器值。 在STM32中,可以采用模拟SPI硬件SPI与AD7799通信,具体实现方式取决于使用的STM32型号和开发环境。以下是一些可能使用的代码和说明: 1. 模拟SPI方式: ```c // 初始化GPIO口 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // 初始化SPI void SPI_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB,&GPIO_InitStructure); } void AD7799_SPI_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); } // SPI发送数据 uint8_t AD7799_SPI_Write(uint8_t data) { uint8_t i; for(i = 0; i < 8; i++) { if(data & 0x80) GPIO_SetBits(GPIOB, GPIO_Pin_9); else GPIO_ResetBits(GPIOB, GPIO_Pin_9); data <<= 1; GPIO_ResetBits(GPIOB, GPIO_Pin_10); GPIO_SetBits(GPIOB, GPIO_Pin_10); } return data; } // SPI接收数据 uint8_t AD7799_SPI_Read(void) { uint8_t i, data = 0; for(i = 0; i < 8; i++) { data <<= 1; GPIO_ResetBits(GPIOB, GPIO_Pin_10); if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)) data |= 0x01; GPIO_SetBits(GPIOB, GPIO_Pin_10); } return data; } ``` 2. 硬件SPI方式: ```c // 初始化SPI void AD7799_SPI_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); } // SPI发送数据 uint8_t AD7799_SPI_Write(uint8_t data) { while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, data); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); return SPI_I2S_ReceiveData(SPI1); } ``` 上述代码只是示例,具体实现方式需要根据您的应用场景进行调整。同时,还需要编写读取和写入AD7799寄存器的函数,例如: ```c // AD7799写寄存器函数 void AD7799_WriteReg(uint8_t reg, uint16_t value) { AD7799_SPI_Write(reg << 3); AD7799_SPI_Write(value >> 8); AD7799_SPI_Write(value & 0xFF); } // AD7799读寄存器函数 uint16_t AD7799_ReadReg(uint8_t reg) { uint16_t value = 0; AD7799_SPI_Write((reg << 3) | 0x04); value |= AD7799_SPI_Read() << 8; value |= AD7799_SPI_Read(); return value; } ``` 以上是一个简单的STM32-24位AD7799驱动手册代码详解。希望能帮助到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Level-6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值