【蓝桥杯物联网赛项学习日志】Day3 关于IIC

news2025/1/16 1:58:18

经过昨天的学习,已经了解和初步学会配置CubeMax进行初始化配置。今天就开始下一章节的学习,关于IIC。

关键词:I2C OLED SSD1306

理论基础

串行通信接口通讯方式分,可以分为两种,分别是同步和异步。按照数据的传输方向又可分为单工、半双工和全双工通信。
同步:通讯双方靠一根时钟线约定通讯速率
异步:通讯双方可以使用各自的通讯时钟,约定通讯速率进行通信
单工:单方向通信,只能收数据或者只能发数据
半双工:可以分时发收数据
全双工:可以同时发收数据,单独时钟线


IIC 简介


IIC(Inter-Integrated Circuit)总线是一种由 PHILIPS 公司开发的两线式串行总线,用于连接
微控制器及其外围设备。它是由数据线 SDA 时钟 SCL 构成的串行总线,可发送和接收数据。
在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。
I2C 总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答
信号。
传输类型同步、半双工,带数据应答
开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,
表示已收到数据。CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接
收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为
受控单元出现故障。
这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。

 GPIO引脚配置

查询文档可知OLED显示屏使用的是PA8,PB4,PB5 三个引脚

 在STM32L071上有两个硬件I2C接口,记作I2C1 I2C3,全都支持I2C标准模式和I2C快速模式。

 在CubeMax中配置iic3

1.单击I2C3
2.选择I2C
3.配置引脚模式,单击GPIO Settings(默认配置也可以)

PA8:    I2C3_SCL,复用开漏模式,上拉,超高速
PB4:    I2C3_SDA,复用开漏模式,上拉,超高速

4. 注意配置初始化PB5引脚,这是OLED的电源控制引脚。

配置完成后生成初始化程序(时钟配置,生成代码请参考上一篇笔记)

I2C库函数

初始化函数:

HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);

hi2c:  指的是I2C句柄; 初始化I2C的名称,定时值,自身地址1,地址模式(7位)或(10位)结构体参数。

主设备发送:

I2C数据传输此处采用的是阻塞式数据传输。阻塞式数据传输使用方便,且I2C接口传输速率不高,一般传输数据量也不大,阻塞式传输是常用的数据传输模式。

HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);

DevAddress:器件地址
pData:发送的数据指针
Size:发送的数据数量
Timeout:超时(ms)

主设备接收函数:

HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,uint16_t Size, uint32_t Timeout);

OLED软件设计与实现:

物联网竞赛平台使用的是128*32 OLED显示屏,I2C接口,控制器是SSD1306。
竞赛会给OLED驱动程序的的资源包,在此基础上进行修改完成OLED软件设计部分。

底层函数

1.在i2c.h中添加以下函数声明

/* USER CODE BEGIN Prototypes */
void OLED_Write(uint8_t ucType,uint8_t ucData);
/* USER CODE END Prototypes */

2.在i2c.c中MX_I2C3_Init()后面部分添加延时

  /* USER CODE BEGIN I2C3_Init 2 */
  HAL_Delay(100);					/* 等待OLED电源稳定 */
  /* USER CODE END I2C3_Init 2 */

3.在i2c.c中添OLED_Write();用来写入OLED数据

/* USER CODE BEGIN 1 */
void OLED_Write(uint8_t ucType,uint8_t ucData)
{
	uint8_t pData[2];
	
	pData[0] = ucType;
	pData[1] = ucData;
	HAL_I2C_Master_Transmit(&hi2c3,0x78,pData,2,10);
}

/* USER CODE END 1 */

高层函数

添加头文件 oled.h

#ifndef __OLED_H
#define __OLED_H

#include "main.h"
#include "i2c.h"


#define Max_Column 128
#define Max_Row 32

typedef enum
{
		TYPE_COMMAND = 0,
		TYPE_DATA = 0x40
}OLED_TYPE;


void OLED_Init(void);	
void OLED_Clear(void);
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size);
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t size);
#endif

添加.C文件

#include "stm32l0xx.h"                  // Device header
#include "oled.h"
#include "font.h"
#include "i2c.h"
/**
  * @brief  OLED设置位置
  * @param  x横坐标,y纵坐标
  * @retval 无
  */
void OLED_SetPos(uint8_t x,uint8_t y)
{
	OLED_Write(TYPE_COMMAND,x & 0x0f);
	OLED_Write(TYPE_COMMAND,0x10 +((x &0xf0) >> 4));
	OLED_Write(TYPE_COMMAND,0xb0 + y);
}
/* 清除屏幕 */
void OLED_Clear(void)
{
  uint8_t i, j;

  for(i = 0; i < 4; i++)
  {
    OLED_SetPos(0, i);
    for(j = 0; j < 128; j++)
      OLED_Write(TYPE_DATA, 0);
  }
}
/**
  * @brief OLED屏幕初始化。
  * @param None
  * @retval None
  */
void OLED_Init(void)
{
  OLED_Write(TYPE_COMMAND, 0xA1);	/* 段重映射, b0:0,0->0(复位值);1,0->127 */

  OLED_Write(TYPE_COMMAND, 0xA8);	/* 复用比 */
	OLED_Write(TYPE_COMMAND, 0x1F);	/* 0F~3F,16MUX~64MUX(复位值) */

  OLED_Write(TYPE_COMMAND, 0xC8);	/* COM扫描方向, b3:0,正常模式(复位值);b3:1,反转模式 */

  OLED_Write(TYPE_COMMAND, 0xDA);	/* COM引脚配置 */
  OLED_Write(TYPE_COMMAND, 0x00);	/* D4:0,顺序;1,交替(复位值) */

	OLED_Write(TYPE_COMMAND, 0x8D);	/* 充电泵 */
  OLED_Write(TYPE_COMMAND, 0x14);	/* D2:0,禁止(复位值);1,允许 */

  OLED_Clear();										/* 清除屏幕 */
  OLED_Write(TYPE_COMMAND, 0xAF);	/* 开启显示 */
}

/**
  * @brief OLED屏幕显示一个字符。
  * @param x 横向选择位置;
					 y 纵向选择位置;
					 chr 需要显示的字符;
					 size 需要显示的字符大小;
					 @arg 16,选择8*16点阵大小字符。其他均选择6*8点阵字符
  * @retval None
  */
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size)
{
    uint8_t  c, i;

  	c = chr - ' ';
    if(x > Max_Column - 1)
    {
        x = 0;
        y = y + 2;
    }
    if(size == 16)
    {
        OLED_SetPos(x, y);
        for(i = 0; i < 8; i++)
            OLED_Write(TYPE_DATA, g_F8X16[c * 16 + i]);
        OLED_SetPos(x, y + 1);
        for(i = 0; i < 8; i++)
            OLED_Write(TYPE_DATA, g_F8X16[c * 16 + i + 8]);
    }
    else
    {
        OLED_SetPos(x, y);
        for(i = 0; i < 6; i++)
        {
            OLED_Write(TYPE_DATA, g_F6x8[c][i]);
        }
    }
}

/**
  * @brief OLED屏幕显示一个字符串。
  * @param x 横向选择位置;0
					 y 纵向选择位置;
					 chr 需要显示的字符串;
					 size 需要显示的字符大小;

  * @retval None
  */
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t size)
{
    uint8_t j = 0;
	
    while(chr[j] != '\0')
    {
        OLED_ShowChar(x, y, chr[j], size);
        x += 8;
        if(x > 120)
        {
            x = 0;
            y += 2;
        }
				j++;
    }
}

主函数

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C3_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
	OLED_Init();
	sprintf((char*)ucBufs, "HELLO!");
	OLED_ShowString(0,0,ucBufs,16);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		
		HAL_Delay(500);
		HAL_GPIO_TogglePin(LD5);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

实验现象

 写一个简单的时钟

在主函数中添加三个时间变量

uint8_t ucSec,ucMin,ucHour;                 	/* 秒计时 分计时 小时 */

在系统定时器,void SysTick_Handler(void)中添加如下代码

void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */
  usDly++;
  if(++usTms == 1000)     			/* 1s到 */
  {
    usTms = 0;
    ucSec++;                 		/* 秒加1 */
  }
	if(ucSec == 60)
	{
		ucSec = 0;
		ucMin++;
	}
	if(ucMin == 60)
	{
		ucMin = 0;
		ucHour ++;
        if(ucHour==24)
            ucHour=0;
	}
	
  /* USER CODE END SysTick_IRQn 1 */
}

在主函数中添加以下代码

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C3_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
    OLED_Init();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		
		HAL_Delay(500);
		HAL_GPIO_TogglePin(LD5);
	    sprintf((char*)ucBuf, "TIME: %02u:%02u:%02u", ucHour, ucMin, ucSec);
        OLED_ShowString(0, 0, ucBuf, 16);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

实验现象

OLED显示时间,LD5闪烁

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/10421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

组成目标货币的最少张数

1、题目 arr 是货币数组&#xff0c;其中的值都是正数。再给定一个正数 aim。 每个值都认为是一张货币&#xff0c;返回组成 aim 的最少张数。 注意&#xff1a;因为是求张数&#xff0c;所以每张货币认为是相同或不同就不重要了。 2、思路 假设 arr [3&#xff0c;1&…

GD32F450的时钟笔记

GD32F450 标称 200MHz&#xff0c;但是在手册中又说 它是 240MHz。本文以 手册中的 240MHz 进行举例&#xff0c;我保险起见&#xff0c;产品中使用还是在 200MHz 下使用。 时钟树 手册上的时钟树图如下 GD32F450的 外部时钟源 有2个 LXTAL 外部低速时钟源 32.768 kHzHXTAL …

微信小程序登录获取不到头像和昵称解决办法!

微信小程序登录获取不到头像和昵称主要原因是&#xff1a;小程序wx.getUserProfile接口被收回&#xff01; 大家可以按照文档操作↓ PS&#xff1a; 针对小程序wx.getUserProfile接口将被收回后做出的授权调整 小程序文档中提出的调整说明 对于此次变化&#xff0c;现将小…

怎么使用股票委托下单接口?

都知道&#xff0c;在进行量化交易的时候&#xff0c;交易接口可以100%严格按照定制的计划执行交易&#xff0c;避免了出现下单犹豫和过量交易等问题&#xff0c;100%体现交易策略的收益性&#xff1b;今天主要来聊聊&#xff0c;关于怎么使用股票委托下单接口的问题&#xff1…

使用c#将aj-report桌面化1

说到底,aj-report是个工具,我想大多数人还是想快速使用它来创建一个可以展示的工具。通过之前的章节,你应该可以制作自己的报表页面了,下面我们来看看怎么把aj-report包装成一个桌面能够运行的软件。 当然作为扩展开发,受开源协议限制,我们不能大规模修改aj-report的源代…

[附源码]java毕业设计基于新高考模式下的排课系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

程序员“中年危机”?不,也可能是“人生转机”

程序员行业新技术发展迅猛&#xff0c;可以说是日新月异。也正是这个原因&#xff0c;中年危机成为我们必须面对和攻克的问题。 思考一个问题&#xff1a;那些能工作到45、50、甚至60的程序员们&#xff0c;究竟具备了哪些过人的能力&#xff1f; 就我过去的经历和观察来说&a…

【蓝桥杯真题练习】STEMA科技素养练习题库 答案版015 持续更新中~

1、牛顿运动定律描述了物体运动符合的规律,被誉为经典力学的基石。以下关于牛顿定律的描述中,不正确的选项是( )。 A、牛顿运动定律一共有三条 B根据牛顿定律,没有受到外力作用的物体运动速度会保持不变 C根据牛顿运动定律,两个物体作用于对方的力大小一定相等 D牛…

项目运营后阶段发力

前言 我记得之前有人跑过来问我&#xff1a;你知道为啥字节面试总会考算法吗&#xff1f;我没有回答&#xff0c;一方面是算法是大厂必考的东西&#xff0c;既然是必须的东西究竟个为什么有点白费心机&#xff0c;第二方面我没有进去过字节&#xff0c;所以我也拿捏不准为什么。…

业务数据分析-Excel的基础操作(一)

Excel的基础操作1、工作簿2、工作表3、数据基本操作4、数据类型5、常用快捷键1、工作簿 即Excel文档&#xff0c;用来储存和处理数据的文件 常用扩展名&#xff1a; xls 97-03版xlsx 07版以后xlsm 带宏的文件 一个工作簿包含多张工作表 2、工作表 默认名称&#xff1a;shee…

【小程序】微信小程序自定义组件Component详细总结

1- 前言 在本文中你将收获 小程序如何使用自定义组件自定义组件之间的传值自定义组件中插槽的使用 2- 组件文件新建 2.1 定义组件 在根目录新建components文件夹&#xff0c;建立cell 文件夹&#xff0c;右击创建cell的Component组件 cell.jscell.wxmlcell.jsoncell.wxss …

mmlab花朵分类结果展示(2)

花朵分类结果展示Grad-Cam可视化方法模型分析折线图和平均耗时展示计算量展示这一节我们继续上一节讲解训练结果测试与验证。Grad-Cam可视化方法 上一节我们讲述了数据增强的可视化方法&#xff0c;因为数据增强是训练模型前的步骤&#xff0c;所以即使我们没有训练结果也可以…

水稻插秧机分叉机构壳体零件数控加工工艺工装设计

目录 &#xff08;一&#xff09;产品介绍-------------------------------------------------------------------1 &#xff08;二&#xff09;计算生产纲领-------------------------------------------------------------2 1&#xff0c;计算生产纲领决定生产类型 2&#x…

【k哥爬虫普法】非法入侵计算机信息系统,获取1500万余条个人信息!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rZDkxIyG-1668593948055)(https://s2.loli.net/2022/11/07/Lx2ZiWGpanJbOvc.png)] 我国目前并未出台专门针对网络爬虫技术的法律规范&#xff0c;但在司法实践中&#xff0c;相关判决已屡见不鲜&#x…

Mybatis---从入门到深化

一、什么是框架&#xff1f; 框架即一个半成品软件。开发者从头开发一个软件需要花费大量精力&#xff0c;于是有一些项目组开发出半成品软件&#xff0c;开发者在这些软件的基础上进行开发&#xff0c;这样的软件就称之为框架。 如果将开发完成的软件比作是一套已经装修完毕的…

超级实用的电脑小技巧大全

技巧一&#xff1a; 一些用户正在经历缓慢和间歇性的下载速度。 解决方案&#xff1a; 比如小编在下载界面做了温馨提示&#xff0c;要求用户在使用本软件前&#xff0c;退出电脑上安装的任何杀毒软件&#xff08;360安全卫士、QQ管家、金山卫士、百度卫士等&#xff09;&am…

C语言 - 通讯录详解

通讯录 文章目录1. 基本思路2.代码实现2.1 定义各种**宏**和**结构体**。2.2 创建结构体并进行初始化2.3 打印菜单&#xff0c;模拟用户的选择2.4 增加联系人2.5 删除联系人2.6 查找联系人2.7 修改联系人2.8 对通讯录进行升序排序2.9 打印通讯录2.10 结束程序并销毁通讯录3. 文…

再度入榜 | 中睿天下入选《中国网络安全企业100强》

近日&#xff0c;国内权威网络安全媒体、第三方安全咨询机构安全牛发布第十版《中国网络安全企业100强》&#xff08;以下简称“百强”&#xff09;&#xff0c;中睿天下以强大的综合发展实力和强劲的发展势头再次荣登百强榜单。 安全牛作为国内网络安全行业权威媒体&#xff0…

能解决你80%关于存储的疑惑

概述 在计算机系统中&#xff0c;常用的存储介质包括寄存器、内存、SSD、磁盘等&#xff0c;寄存器的速写速度与CPU相同&#xff0c;一个时钟周期是0.3纳秒&#xff0c;而内存访问需要120纳秒&#xff0c;寄存器的读写速度比内存要快几百倍&#xff0c;固态硬盘访问需要50&…

Vue3基础(26)___defineProps、defineEmits、defineExpose组件通信

defineProps、defineEmits、defineExpose组件通信 在使用这个之前&#xff0c;我们需要知道setup的语法糖写法&#xff0c;因为上面的三个api需要在这个语法糖中才能使用&#xff1a; <script setup>console.log(LiuQing) </script>里面的代码会被编译成组件 set…