NB

您所在的位置:网站首页 NB-IoT通信选什么型号好 NB

NB

2024-07-13 18:54| 来源: 网络整理| 查看: 265

STM32基础实验

上一节介绍了江苏学蠡信息科技有限公司的无线传感器网络实验平台关于NB-IOT实验所需要的各项硬件以及所需要的软件组成部分,这一章,主要是使用STM32F103单片机的基础实验进行介绍和演示。

1. 使用STM32CubeMX创建工程

STM32的开发目前一共有三种方式:

直接配置寄存器 直接配置寄存器的方式源于对51单片机的学习,但是使用直接配置寄存器的方式来学习STM32,对于新手小白而言无疑是灭顶之灾。STM32的寄存器远多于51系列单片机十多倍,这么多的寄存器能全记下来已经是实属不易,更别提去配置寄存器了。虽然也有追求大道根本的大佬会使用这种办法,可以直接接触到底层更好的掌握原理。标准库 因为STM32的寄存器数量太多,ST公司就为每一款芯片都编写了一份库文件,就是常见的stm32F1xx什么之类的,在这些.c和.h文件中将各芯片所要用到的一些常用量的宏定义和一些外设都通过结构体变量封装起来。所以作为开发人员只需要配置结构体变量成员就可以修改外设的配置寄存器,从而选择不同的功能。目前使用标准库进行学习和开发STM32的人数最多,属于主流学习和开发方式。HAL库 使用HAL库是目前ST公司主推的开发方式,并且目前ST公司已经停止了对标准库的更新维护,以此来看未来ST公司想要的是将HAL库开发作为STM32的主流开发方式。 HAL,英文全称 Hardware Abstraction Layer,即硬件抽象层。HAL 库是 ST 公司提供的外设驱动代码的驱动库,用户只需要调用库的 API 函数,便可间接配置寄存器。我们要写程序控制 STM32 芯片,其实最终就是控制它的寄存器,使之工作在我们需要的模式下,HAL库将大部分寄存器的操作封装成了函数,我们只需要学习和掌握 HAL 库函数的结构和用法,就能方便地驱动 STM32 工作,以节省开发时间。并且HAL库也很好的解决了程序移植的问题,不同型号的stm32芯片它的标准库是不一样的,例如在F4上开发的程序移植到F3上是不能通用的,而使用HAL库,只要使用的是相通的外设,程序基本可以完全复制粘贴。同时采用ST公司的STM32CubeMX软件进行STM32开发,可以依靠图形化界面对单片机的进行功能配置,例如时钟频率、GPIO口、定时器、中断等,可以直接生成整个使用HAL库的工程文件,开发人员只需要调用对应的功能函数完成mian函数的编写就行 但目前使用HAL库进行开发还是存在些许弊端,因为STM32CubeMX是直接一步到位帮我们生成工程文件,所以可能会有很多“累赘”,导致使用HAL库开发的工程文件偏大,同时效率也较低。

在本实验中所使用的STM32开发方式都是采用HAL库和STM32CubeMX进行,对于STM32CubeMX的软件安装就不多做介绍,各位只要双击安装包,改个路径一路next即可。同时需要交代的是我所使用的固件包版本为STM32Cube_FW_F1_V1.8.0,各位在安装完成后在软件包管理页面中下载或者通过本地路径配置都可。

创建工程方式 选择你所开发的STM32单片机的型号 在本无线传感器网络实验平台中,NB-IOT核心模块使用的是STM32F103T8U6,因此在MCU/MPU Selector页面中直接搜索STM32F103T8U6即可。 在这里插入图片描述双击上述图片的芯片型号,进入主设计界面 在这里插入图片描述确认时钟源 进入工程后打开RCC选项,选择Crystal/Ceramic Resonator,即使用外部晶振作为 HSE 的时钟源。 在这里插入图片描述配置系统时钟 硬件的外部晶振为 12MHz,我们填入 12;通道选择 HSE;PLLM 选择为/1;倍频系数 N选择为 x6; 系统时钟选择 PLLCLK;系统时钟设定为 72Mz;APB1 分频系数选择为/2 即PCLK1 位 36MHz; APB2 分频系数选择为/1 即 PCLK2 位 72MHz。 CubeMX 也提供了更简单的方法:在下图的“HCLK(MHz)”位置,实际上是可以编辑的。我们直接输入我们要的主频,这里是 72Mzh,按回车键,CubeMX 会帮我们提供一种设置主频和其它时钟的建议,选择是后会由软件自动配置好,当然只有启用外部的晶振后才能配置到 72Mhz 的时钟。 在这里插入图片描述配置IO口 首先以一个简单的LED灯周期闪烁为例的工程,进行IO口的配置,我们需要配置两个 IO 即可,控制 LED 的引脚分别为 PB2 PB3,通过搜索框搜索可以定位 IO 口的引脚位置, 图中会闪烁显示,配置 PB2、PB3 的属性为 GPIO_Output。 在这里插入图片描述进一步配置IO的具体属性 双击PB2,进入详细配置,选择 GPIO,配置 PB2 PB3 的默认电平,开漏输出,无上下拉,高速模式。引脚标签为 LED0 和 LED1。 在这里插入图片描述配置工程属性 为了防止出现,烧录以后仿真器无法连接的情况,我们在 Pinout 里将 SYS 里面的 Debug设置成 Serial Wire。 在这里插入图片描述选择 Project Manager 选项,配置工程的名称,路径,使用的 IDE 工具,堆栈大小。 注意路径中不要出现中文 在这里插入图片描述生成代码 打开 Project Manager-> Code Generator 选项,Generated files 生成文件选项,勾选Generate peripheral initialization as a pair of ‘.c/.h’files per peripheral,勾选这个选项的话将会将每个外设单独分开成一组.c、.h 文件,使得代码结构更加的清晰。由于 CubeMX 默认勾选了复制所有的库,即工程中不使用到的代码也会复制进来,为了节省 CubeMX 生成工程的空间,我们勾选生成工程时只复制用到的库(这一步是可选操作,大家根据自己的实际选择)。点击 GENERATE CODE, 在设定的路径成功生成代码,选择打开工程。 在这里插入图片描述编写用户代码 到这可以说新建工程的事情就已经告一段落了,接下来只需要在main函数中编写你需要的代码即可。因为使用的示例程序是LED灯周期闪烁,所以在main 函数中的编码如下: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(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); HAL_Delay(500); HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); HAL_Delay(500); } /* USER CODE END WHILE */ 配置下载调试工具 在Keil中点击“魔术棒”按钮,设置下载工具为ST-link Debuger,程序下载完后复位并运行(一定要复位,不复位不出现象)。 在这里插入图片描述下载验证 把编译好的程序下载到硬件并复位,可看到 NB-IOT 模块上的两颗红色 LED 灯会交替周期闪烁。(下载器与液晶扩展板的连接方式请参考上一篇文章——NB-IOT实验练习1中对于仿真器/编程器处) 在这里插入图片描述 2. STM32基础实验 2.1 按键输入实验 实验目的:了解并掌握按键的使用方法和工作原理。实验现象:当按下按键时,LED 会闪烁。所需硬件:一个液晶扩展板、一个 NB-IOT 核心模块、一个 ST-Link 仿真器、1 根 mini USB 线、1 台 PC 机硬件引脚说明: MCU引脚号按键引脚说明按键编号PA5P_06K4(垂直向下按下) 硬件电路原理图: 在这里插入图片描述编码

按照STM32CubeMX创建工程小节里的流程,进行所用GPIO的配置,直接生成工程文件。

在编写按键驱动时,也要考虑更改硬件环境的情况。我们把按键检测引脚相关的宏定义在“bsp_key.h”文件中。以下代码根据按键的硬件连接,把检测按键输入的 GPIO 端口、GPIO 引脚号以及 GPIO 端口时钟封装起来了。

//引脚定义 /*******************************************************/ #define KEY_PIN GPIO_PIN_5 #define KEY_GPIO_PORT GPIOA #define KEY_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() /*******************************************************/

按键 GPIO 初始化函数

void Key_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /*开启按键 GPIO 口的时钟*/ KEY_GPIO_CLK_ENABLE(); /*选择按键的引脚*/ GPIO_InitStructure.Pin = KEY_PIN; /*设置引脚为输入模式*/ GPIO_InitStructure.Mode = GPIO_MODE_INPUT; /*设置引脚不上拉也不下拉*/ GPIO_InitStructure.Pull = GPIO_NOPULL; /*使用上面的结构体初始化按键*/ HAL_GPIO_Init(KEY_GPIO_PORT, &GPIO_InitStructure); }

按键状态检测

uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin) { /*检测是否有按键按下 */ if(HAL_GPIO_ReadPin(GPIOx,GPIO_Pin) == KEY_ON ) { HAL_Delay(10); //延时消抖 if(HAL_GPIO_ReadPin(GPIOx,GPIO_Pin) == KEY_ON ) { /*等待按键释放 */ while(HAL_GPIO_ReadPin(GPIOx,GPIO_Pin) == KEY_ON); return KEY_ON; } else return KEY_OFF; } else return KEY_OFF; }

5.主函数

int main(void) { /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* LED 端口初始化 */ LED_GPIO_Config(); /*初始化按键*/ Key_GPIO_Config(); /* 轮询按键状态,若按键按下则反转 LED */ while(1) { if(Key_Scan(KEY_GPIO_PORT, KEY_PIN) == KEY_ON) { /*LED1 反转*/ LED1_TOGGLE; } } } 实验效果: 按下按键,松开后控制LED亮灭 在这里插入图片描述 2.2 外部中断实验 实验目的:了解并掌握 STM32 的外部中断的配置方法。实验现象:通过外部中断,实现按键控制 LED 亮灭。所需硬件:一个液晶扩展板、一个 NB-IOT 核心模块、一个 ST-Link 仿真器、1 根 mini USB 线、1 台 PC 机硬件引脚说明: MCU引脚号按键引脚说明按键编号PA5P_06K4(垂直向下按下) 硬件电路原理图:

在这里插入图片描述

编码

按照STM32CubeMX创建工程小节里的流程,进行所用GPIO的配置,直接生成工程文件。

我们创建了两个文件:bsp_exti.c 和 bsp_exti.h 文件用来存放 EXTI 驱动程序及相关宏定义,中断服务函数放在 stm32f1xx_it.h 文件中。

按键和 EXTI 宏定义

//引脚定义 /*******************************************************/ #define KEY_INT_GPIO_PORT GPIOA #define KEY_INT_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE(); #define KEY_INT_GPIO_PIN GPIO_PIN_5 #define KEY_INT_EXTI_IRQ EXTI9_5_IRQn #define KEY_IRQHandler EXTI9_5_IRQHandler /*******************************************************/

EXTI 中断配置

void EXTI_Key_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /*开启按键 GPIO 口的时钟*/ KEY_INT_GPIO_CLK_ENABLE(); /* 选择按键的引脚 */ GPIO_InitStructure.Pin = KEY_INT_GPIO_PIN; /* 设置引脚为输入模式 */ GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING; /* 设置引脚不上拉也不下拉 */ GPIO_InitStructure.Pull = GPIO_NOPULL; /* 使用上面的结构体初始化按键 */ HAL_GPIO_Init(KEY_INT_GPIO_PORT, &GPIO_InitStructure); /* 配置 EXTI 中断源 到 key 引脚、配置中断优先级*/ HAL_NVIC_SetPriority(KEY_INT_EXTI_IRQ, 0, 0); /* 使能中断 */ HAL_NVIC_EnableIRQ(KEY_INT_EXTI_IRQ); }

EXTI 中断服务函数

void KEY_IRQHandler(void) { //确保是否产生了 EXTI Line 中断 if(__HAL_GPIO_EXTI_GET_IT(KEY_INT_GPIO_PIN) != RESET) { // LED1 取反 LED1_TOGGLE; //清除中断标志位 __HAL_GPIO_EXTI_CLEAR_IT(KEY_INT_GPIO_PIN); } }

主函数

int main(void) { /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* LED 端口初始化 */ LED_GPIO_Config(); /* 初始化 EXTI 中断,按下按键会触发中断, * 触发中断会进入 stm32f7xx_it.c 文件中的函数 * KEY_IRQHandler 处理中断,反转 LED 灯。 */ EXTI_Key_Config(); /* 等待中断,由于使用中断方式,MCU 不用轮询按键 */ while(1) { } } 实验效果: 按下按键,松开后控制LED亮灭 在这里插入图片描述 2.3 SysTick 定时器实验 实验目的:了解并掌握 STM32 的 SysTick 定时器的配置方法。实验现象:利用 SysTick 产生 1s 的时基,LED 以 1s 的频率闪烁。所需硬件:一个液晶扩展板、一个 NB-IOT 核心模块、一个 ST-Link 仿真器、1 根 mini USB 线、1 台 PC 机硬件引脚说明:使用单片机内部电路,无需外设介入编码: 创建了两个文件:bsp_SysTick.c 和 bsp_ SysTick.h 文件用来存放 SysTick 驱动程序及相关宏定义,中断服务函数放在 stm32f1xx_it.c 文件中。SysTick 配置库函数STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { // 不可能的重装载值,超出范围 if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); } // 设置重装载寄存器 SysTick->LOAD = (uint32_t)(ticks - 1UL); // 设置中断优先级 NVIC_SetPriority (SysTick_IRQn, (1UL CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; return (0UL); } 配置 SysTick 中断优先级// 设置系统定时器中断优先级 NVIC_SetPriority (SysTick_IRQn, (1UL USART1_RX */ /* 配置 Tx 引脚为复用功能 */ GPIO_InitStruct.Pin = DEBUG_USART_TX_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStruct); /* 配置 Rx 引脚为复用功能 */ GPIO_InitStruct.Pin = DEBUG_USART_RX_PIN; GPIO_InitStruct.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式! HAL_GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStruct); // HAL_NVIC_SetPriority(DEBUG_USART_IRQ ,0,1); //抢占优先级 0,子优先级 1 // HAL_NVIC_EnableIRQ(DEBUG_USART_IRQ ); //使能 USART1 中断通道 } 重定向 printf 和 scanf 函数//重定向 c 库函数 printf 到串口 DEBUG_USART,重定向后可使用 printf 函数 int fputc(int ch, FILE *f) { /* 发送一个字节数据到串口 DEBUG_USART */ HAL_UART_Transmit(&UartHandle, (uint8_t *)&ch, 1, 1000); return (ch); } //重定向 c 库函数 scanf 到串口 DEBUG_USART,重写向后可使用 scanf、getchar 等函数 int fgetc(FILE *f) { int ch; HAL_UART_Receive(&UartHandle, (uint8_t *)&ch, 1, 1000); return (ch); } 输出提示信息/** * @brief 打印指令输入提示信息 * @param 无 * @retval 无 */ static void Show_Message(void) { printf("\r\n 这是一个通过串口通信指令控制 LED 灯实验 \r\n"); printf("硬件接到指令后控制 LED 灯亮灭,指令对应如下:\r\n"); printf(" 指令 ------ LED 灯序号 \r\n"); printf(" 1 ------ LED1 \r\n"); printf(" 2 ------ LED2 \r\n"); } 主函数int main(void) { char ch; /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* LED 端口初始化 */ LED_GPIO_Config(); /*初始化 USART 配置模式为 115200 8-N-1,中断接收*/ DEBUG_USART_Config(); /* 打印指令输入提示信息 */ Show_Message(); while(1) { /* 获取字符指令 */ ch=getchar(); printf("接收到字符:%c\r\n",ch); /* 根据字符指令控制 LED 灯亮灭 */ switch(ch) { case '1': LED1_TOGGLE; break; case '2': LED2_TOGGLE; break; default: /* 如果不是指定指令字符,打印提示信息 */ Show_Message(); break; } } } 实验效果 复位 NB-IOT 节点后,保证硬件相关硬件连接正确,用 mini USB 线连接液晶扩展板的 USB接口,另外一端接至电脑。在电脑端打开串口调试助手并配置好相关参数并打开串口: 波特率:115200数据位: 8停止位:1 在这里插入图片描述 在“字符串输入框”中输入命令 1 或 2,点击“发送”按钮,观察 NB-IOT 模块上的两颗LED 会相应的亮灭。 在这里插入图片描述 2.5 ADC 实验

实验目的:了解 ADC 的原理,并掌握如何使用 STM32 的 ADC 采集方向按键按下不同方向的采集电压值。

实验现象:打开“串口调试助手”,拨动方向按键不同方向传输打印输出不同的电压值信息。

所需硬件:一个液晶扩展板、一个 NB-IOT 核心模块、一个 ST-Link 仿真器、1 根 mini USB 线、1 台 PC 机

硬件说明: 方向按键的检测引脚通过连接至 STM32 芯片的 ADC 通道引脚。当我们拨动方向按键不同方向时,其检测引脚的电压也会随之改变,电压变化范围为 0~3.3V,亦是硬件默认的ADC 电压采集范围。(需要说明的是,液晶扩展板上有一个串口选择开关,我们需要将它拨至右侧) 硬件原理图: 在这里插入图片描述 在这里插入图片描述

编码:

ADC 宏定义// ADC GPIO 宏定义 #define RHEOSTAT_ADC_GPIO_PORT GPIOA //改为 PA5 #define RHEOSTAT_ADC_GPIO_PIN GPIO_PIN_5 #define RHEOSTAT_ADC_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() // ADC 序号宏定义 #define RHEOSTAT_ADC ADC1 #define RHEOSTAT_ADC_CLK_ENABLE() __HAL_RCC_ADC1_CLK_ENABLE(); #define RHEOSTAT_ADC_CHANNEL ADC_CHANNEL_5 //通道 5 // ADC 中断宏定义 #define Rheostat_ADC_IRQ ADC1_IRQn #define Rheostat_ADC_INT_FUNCTION ADC1_IRQHandler ADC GPIO 初始化函数static void Rheostat_ADC_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RHEOSTAT_ADC_CLK_ENABLE(); // 使能 GPIO 时钟 RHEOSTAT_ADC_GPIO_CLK_ENABLE(); // 配置 IO GPIO_InitStructure.Pin = RHEOSTAT_ADC_GPIO_PIN; GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; GPIO_InitStructure.Pull = GPIO_NOPULL ; //不上拉不下拉 HAL_GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure); } 配置 ADC 工作模式static void Rheostat_ADC_Mode_Config(void) { RCC_PeriphCLKInitTypeDef ADC_CLKInit; // 开启 ADC 时钟 //ADC 外设时钟 ADC_CLKInit.PeriphClockSelection=RCC_PERIPHCLK_ADC; //分频因子 6 时钟为 72M/6=12MHz ADC_CLKInit.AdcClockSelection=RCC_ADCPCLK2_DIV6; //设置 ADC 时钟 HAL_RCCEx_PeriphCLKConfig(&ADC_CLKInit); ADC_Handle.Instance=RHEOSTAT_ADC; //右对齐 ADC_Handle.Init.DataAlign=ADC_DATAALIGN_RIGHT; //非扫描模式 ADC_Handle.Init.ScanConvMode=DISABLE; //连续转换 ADC_Handle.Init.ContinuousConvMode=ENABLE; //1 个转换在规则序列中 也就是只转换规则序列 1 ADC_Handle.Init.NbrOfConversion=1; //禁止不连续采样模式 ADC_Handle.Init.DiscontinuousConvMode=DISABLE; //不连续采样通道数为 0 ADC_Handle.Init.NbrOfDiscConversion=0; //软件触发 ADC_Handle.Init.ExternalTrigConv=ADC_SOFTWARE_START; //初始化 HAL_ADC_Init(&ADC_Handle); //------------------------------ ADC_Config.Channel = RHEOSTAT_ADC_CHANNEL; ADC_Config.Rank = 1; // 采样时间间隔 ADC_Config.SamplingTime = ADC_SAMPLETIME_55CYCLES_5 ; // 配置 ADC 通道转换顺序为 1,第一个转换,采样时间为 3 个时钟周期 HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_Config); HAL_ADC_Start_IT(&ADC_Handle); } ADC 中断配置// 配置中断优先级 static void Rheostat_ADC_NVIC_Config(void) { HAL_NVIC_SetPriority(Rheostat_ADC_IRQ, 0, 0); HAL_NVIC_EnableIRQ(Rheostat_ADC_IRQ); } ADC 中断服务函数/** * @brief This function handles ADC interrupt request. * @param None * @retval None */ void ADC1_IRQHandler(void) { HAL_ADC_IRQHandler(&ADC_Handle); } /** * @brief 转换完成中断回调函数(非阻塞模式) * @param AdcHandle : ADC 句柄 * @retval 无 */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle) { /* 获取结果 */ ADC_ConvertedValue = HAL_ADC_GetValue(AdcHandle); } 主函数int main(void) { /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* LED 端口初始化 */ LED_GPIO_Config(); /*初始化 USART 配置模式为 115200 8-N-1,中断接收*/ DEBUG_USART_Config(); Rheostat_Init(); while (1) { ADC_Vol =(float) ADC_ConvertedValue/4096*(float)3.3; // 读取转换的 AD 值 printf("\r\n The current AD value = 0x%04X \r\n", ADC_ConvertedValue); printf("\r\n The current AD value = %f V \r\n",ADC_Vol); Delay(0x8fffff); } }

实验现象: 复位 NB-IOT 节点后,保证硬件相关硬件连接正确,用 mini USB 线连接液晶扩展板的 USB接口,另外一端接至电脑。在电脑端打开串口调试助手并配置好相关参数并打开串口:

波特率:115200数据位: 8停止位:1

当我们拨动方向按键不同方向时,其检测引脚的电压也会随之改变,电压变化范围为0~3.3V。 在这里插入图片描述

2.6 OLED 屏显示实验 实验目的:了解 IIC 协议及 OLED 显示的原理,并掌握如何使用 STM32 的 IIC 总线驱动 OLED模块显示 ASCII 码字符。实验现象:使用 IIC 模式驱动,驱动 OLED 模块,不停的显示 ASCII 码字符。所需硬件:一个液晶扩展板、一个 NB-IOT 核心模块、一个 ST-Link 仿真器、1 根 mini USB 线、1 台 PC 机硬件引脚说明: MCU引脚号按键引脚说明按键编号PA11SDAP_12PA12SCLP_13PA8使能OLED的电源EXTVDD_3V3P_13 硬件电路原理图: 在这里插入图片描述 在这里插入图片描述编码: 这里使用的是IO口模拟IIC协议进行通信 IIC 硬件相关宏定义#define OLED_SDA_PORT GPIOA #define OLED_SDA_PIN GPIO_PIN_11 #define OLED_SCL_PORT GPIOA #define OLED_SCL_PIN GPIO_PIN_12 #define VCC_3V3_PORT GPIOA #define VCC_3V3_PIN GPIO_PIN_8 初始化 IIC 的 GPIOvoid OLED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); // Init the GPIO pins GPIO_InitStruct.Pin = VCC_3V3_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(VCC_3V3_PORT, &GPIO_InitStruct); GpioWrite(VCC_3V3_PORT, VCC_3V3_PIN, GPIO_PIN_SET); DelayMs(100); // Init the GPIO pins GPIO_InitStruct.Pin = OLED_SDA_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(OLED_SDA_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = OLED_SCL_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(OLED_SCL_PORT, &GPIO_InitStruct); DelayMs(10); ugOled9616int(); } 初始化OLEDstatic void OLED_Init() { Set_Display_On_Off(0x00); // Display Off (0x00/0x01) Set_Display_Clock(0xA2); // Set Clock as 120 Frames/Sec Set_Multiplex_Ratio(0x0F); // 1/16 Duty (0x0F~0x3F) Set_Display_Offset(0x00); // Shift Mapping RAM Counter (0x00~0x3F) Set_Start_Line(0x00); // Set Mapping RAM Display Start Line (0x00~0x3F) Set_Charge_Pump(0x04); // Enable Embedded DC/DC Converter (0x00/0x04) Set_Power_Save(0x05); // Set Low Power Save Mode Set_Addressing_Mode(0x02); // Set Page Addressing Mode (0x00/0x01/0x02) Set_Segment_Remap(0x01); // Set SEG/Column Mapping (0x00/0x01) Set_Common_Remap(0x08); // Set COM/Row Scan Direction (0x00/0x08) Set_Common_Config(0x00); // Set Sequential Configuration (0x00/0x10) Set_Contrast_Control(Brightness); // Set SEG Output Current Set_Precharge_Period(0xD2); // Set Pre-Charge as 13 Clocks & Discharge as 2 Clock Set_VCOMH(0x20); // Set VCOM Deselect Level Set_Entire_Display(0x00); // Disable Entire Display On (0x00/0x01) Set_Inverse_Display(0x00); // Disable Inverse Display On (0x00/0x01) FillRam(0x00); // Clear Screen Set_Display_On_Off(0x01); // Display On (0x00/0x01) } 产生 IIC 起始信号static void I2C_Start() { OLED_SDA_LOW(); uDelay(1); OLED_SCL_HIGH(); uDelay(1); OLED_SCL_LOW(); uDelay(1); } 产生停止信号static void I2C_Stop() { OLED_SCL_HIGH(); uDelay(5); OLED_SDA_LOW(); uDelay(5); OLED_SDA_HIGH(); uDelay(5); } 发送一个字节数据static void IIC_O( OledDataType mcmd ) { OledDataType length = 8; // Send Command while(length--) { if(mcmd & 0x80) { OLED_SDA_HIGH(); } else { OLED_SDA_LOW(); } uDelay(1); OLED_SCL_HIGH(); uDelay(1); OLED_SCL_LOW(); uDelay(1); mcmd = mcmd


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3