NB-IOT实验练习2——STM32基础实验

article/2025/7/10 3:19:09

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,各位在安装完成后在软件包管理页面中下载或者通过本地路径配置都可。

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

2. STM32基础实验

2.1 按键输入实验

  • 实验目的:了解并掌握按键的使用方法和工作原理。
  • 实验现象:当按下按键时,LED 会闪烁。
  • 所需硬件:一个液晶扩展板、一个 NB-IOT 核心模块、一个 ST-Link 仿真器、1 根 mini USB
    线、1 台 PC 机
  • 硬件引脚说明:
MCU引脚号按键引脚说明按键编号
PA5P_06K4(垂直向下按下)
  • 硬件电路原理图:
    在这里插入图片描述
  • 编码
    1. 按照STM32CubeMX创建工程小节里的流程,进行所用GPIO的配置,直接生成工程文件。

    2. 在编写按键驱动时,也要考虑更改硬件环境的情况。我们把按键检测引脚相关的宏定义在“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()
      /*******************************************************/
      
    3. 按键 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);
      }
      
    4. 按键状态检测

      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;}elsereturn KEY_OFF;}elsereturn 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(垂直向下按下)
  • 硬件电路原理图:

在这里插入图片描述

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

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

    3. 按键和 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
      /*******************************************************/
      
    4. 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);
      }
      
    5. 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);}
      }
      
    6. 主函数

      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 机
  • 硬件引脚说明:使用单片机内部电路,无需外设介入
  • 编码:
    1. 创建了两个文件:bsp_SysTick.c 和 bsp_ SysTick.h 文件用来存放 SysTick 驱动程序及相关宏定义,中断服务函数放在 stm32f1xx_it.c 文件中。
    2. 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 << NVIC_PRIO_BITS) - 1UL);
      // 设置当前数值寄存器
      SysTick->VAL = 0UL;
      // 设置系统定时器的时钟源为 AHBCLK=72M
      // 使能系统定时器中断
      // 使能定时器
      SysTick->CTRL
      = SysTick_CTRL_CLKSOURCE_Msk |
      SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
      return (0UL);
      }
      
    3. 配置 SysTick 中断优先级
      // 设置系统定时器中断优先级
      NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
      
    4. SysTick 初始化函数
      void SysTick_Init(void)
      {/* SystemFrequency / 1000 1ms 中断一次* SystemFrequency / 10000010us 中断一次* SystemFrequency / 1000000 1us 中断一次*/if (HAL_SYSTICK_Config(SystemCoreClock / 100000)){/* Capture error */while (1);}
      }
      
    5. SysTick 定时函数
      /**
      * @brief us 延时程序,10us 为一个单位
      * @param
      *
      @arg nTime: Delay_us( 1 ) 则实现的延时为 1 * 10us = 10us
      * @retval 无
      */
      void Delay_us(__IO u32 nTime)
      {TimingDelay = nTime;while(TimingDelay != 0);
      }
      
    6. SysTick 中断服务函数
      /**
      * @brief This function handles System tick timer.
      */
      void SysTick_Handler(void)
      {HAL_IncTick();TimingDelay_Decrement();
      }
      
    7. 主函数
      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();/* 配置 SysTick 为 10us 中断一次,时间到后触发定时中断,*进入 stm32f7xx_it.c 文件的 SysTick_Handler 处理,通过数中断次数计时*/SysTick_Init();while(1){LED1_TOGGLE;Delay_us(100000); // 10000 * 10us = 1000msLED2_TOGGLE;Delay_us(100000); // 10000 * 10us = 1000ms}
      }
      
  • 实验效果:
    复位 NB-IOT 节点后,LED 以 1s 的频率闪烁。
    在这里插入图片描述

2.4 串口通讯实验

  • 实验目的:了解串口通信的原理,并掌握如何使用 STM32 的串口发送和接收数据。
  • 实验现象:在“串口调试助手”输入指令,让硬件根据这些指令执行一些任务,根据数据内容控制 LED 灯的亮灭。
  • 所需硬件:一个液晶扩展板、一个 NB-IOT 核心模块、一个 ST-Link 仿真器、1 根 mini USB
    线、1 台 PC 机
  • 硬件说明:
    为利用 USART 实现硬件与电脑通信,需要用到一个 USB 转 USART 的 IC,我们选择CP2102 芯片来实现这个功能,CP2102 是一个 USB 总线的转接芯片。具体电路设计见下图。
    我们将 CP2102 的 TXD 引脚与 USART1 的 RX 引脚连接,CP2102 的 RXD 引脚与USART1 的 TX 引脚连接。CP2102 芯片集成在液晶扩展板上,其地线 (GND) 已与控制器的GND 连通。(需要说明的是,液晶扩展板上有一个串口选择开关,我们需要将它拨至右侧)
    硬件原理图:
    在这里插入图片描述

在这里插入图片描述

  • 编码:
    1. 创建了两个文件:bsp_usart.c 和 bsp_usart.h 文件用来存放 USART 驱动程序及相关
      宏定义。
    2. GPIO 和 USART 宏定义
      //串口波特率
      #define DEBUG_USART_BAUDRATE 115200
      //引脚定义
      /*******************************************************/
      #define DEBUG_USART USART1
      #define DEBUG_USART_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE();
      #define DEBUG_USART_RX_GPIO_PORT GPIOA
      #define DEBUG_USART_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
      #define DEBUG_USART_RX_PIN GPIO_PIN_10
      #define DEBUG_USART_TX_GPIO_PORT GPIOA
      #define DEBUG_USART_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
      #define DEBUG_USART_TX_PIN GPIO_PIN_9
      #define DEBUG_USART_IRQHandler USART1_IRQHandler
      #define DEBUG_USART_IRQ
      USART1_IRQn
      /************************************************************/
      
    3. USART 初始化配置
      /**
      * @brief DEBUG_USART GPIO 配置,工作模式配置。115200 8-N-1
      * @param 无
      * @retval 无
      */
      void DEBUG_USART_Config(void)
      {UartHandle.Instance = DEBUG_USART;UartHandle.Init.BaudRate = DEBUG_USART_BAUDRATE;UartHandle.Init.WordLength = UART_WORDLENGTH_8B;UartHandle.Init.StopBits = UART_STOPBITS_1;UartHandle.Init.Parity = UART_PARITY_NONE;UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;UartHandle.Init.Mode = UART_MODE_TX_RX;HAL_UART_Init(&UartHandle);
      }/**
      * @brief UART MSP 初始化
      * @param huart: UART handle
      * @retval 无
      */
      void HAL_UART_MspInit(UART_HandleTypeDef *huart)
      {
      GPIO_InitTypeDef GPIO_InitStruct;
      DEBUG_USART_CLK_ENABLE();
      DEBUG_USART_RX_GPIO_CLK_ENABLE();
      DEBUG_USART_TX_GPIO_CLK_ENABLE();
      /**USART1 GPIO Configuration
      PA9 ------> USART1_TX
      PA10 ------> 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 中断通道
      }
      
    4. 重定向 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);
      }
      
    5. 输出提示信息
      /**
      * @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");
      }
      
    6. 主函数
      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 电压采集范围。(需要说明的是,液晶扩展板上有一个串口选择开关,我们需要将它拨至右侧)
    硬件原理图:
    在这里插入图片描述
    在这里插入图片描述

  • 编码:

    1. 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
      
    2. ADC GPIO 初始化函数
      static void Rheostat_ADC_GPIO_Config(void)
      {GPIO_InitTypeDef GPIO_InitStructure;RHEOSTAT_ADC_CLK_ENABLE();// 使能 GPIO 时钟RHEOSTAT_ADC_GPIO_CLK_ENABLE();// 配置 IOGPIO_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);
      }
      
    3. 配置 ADC 工作模式
      static void Rheostat_ADC_Mode_Config(void)
      {RCC_PeriphCLKInitTypeDef ADC_CLKInit;// 开启 ADC 时钟//ADC 外设时钟ADC_CLKInit.PeriphClockSelection=RCC_PERIPHCLK_ADC;//分频因子 6 时钟为 72M/6=12MHzADC_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 个转换在规则序列中 也就是只转换规则序列 1ADC_Handle.Init.NbrOfConversion=1;//禁止不连续采样模式ADC_Handle.Init.DiscontinuousConvMode=DISABLE;//不连续采样通道数为 0ADC_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);
      }
      
    4. ADC 中断配置
      // 配置中断优先级
      static void Rheostat_ADC_NVIC_Config(void)
      {
      HAL_NVIC_SetPriority(Rheostat_ADC_IRQ, 0, 0);
      HAL_NVIC_EnableIRQ(Rheostat_ADC_IRQ);
      }
      
    5. 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);
      }
      
    6. 主函数
      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_12
PA12SCLP_13
PA8使能OLED的电源EXTVDD_3V3P_13
  • 硬件电路原理图:
    在这里插入图片描述
    在这里插入图片描述
  • 编码:
    这里使用的是IO口模拟IIC协议进行通信
    1. 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
      
    2. 初始化 IIC 的 GPIO
      void OLED_GPIO_Config(void)
      {GPIO_InitTypeDef GPIO_InitStruct;__HAL_RCC_GPIOA_CLK_ENABLE();// Init the GPIO pinsGPIO_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 pinsGPIO_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();
      }
      
    3. 初始化OLED
      static void OLED_Init()
      {Set_Display_On_Off(0x00);// Display Off (0x00/0x01)Set_Display_Clock(0xA2);// Set Clock as 120 Frames/SecSet_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 ModeSet_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 CurrentSet_Precharge_Period(0xD2);// Set Pre-Charge as 13 Clocks & Discharge as2 ClockSet_VCOMH(0x20);// Set VCOM Deselect LevelSet_Entire_Display(0x00);// Disable Entire Display On (0x00/0x01)Set_Inverse_Display(0x00);// Disable Inverse Display On (0x00/0x01)FillRam(0x00);// Clear ScreenSet_Display_On_Off(0x01);// Display On (0x00/0x01)
      }
      
    4. 产生 IIC 起始信号
      static void I2C_Start()
      {OLED_SDA_LOW();uDelay(1);OLED_SCL_HIGH();uDelay(1);OLED_SCL_LOW();uDelay(1);
      }
      
    5. 产生停止信号
      static void I2C_Stop()
      {OLED_SCL_HIGH();uDelay(5);OLED_SDA_LOW();uDelay(5);OLED_SDA_HIGH();uDelay(5);
      }
      
    6. 发送一个字节数据
      static void IIC_O( OledDataType mcmd )
      {OledDataType length = 8;// Send Commandwhile(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 << 1;}
      }
      
    7. 主函数
      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();OLED_GPIO_Config(); //OLED 相关引脚定义放在 main.h 文件中HAL_Delay(10);LcdPutScDispRtoL((void*)"ABCDEFG1234567890", 1, 600); //液晶显示/* Infinite loop */while(1){}
      }
      
  • 实验效果:
    复位 NB-IOT 节点后,OLED 模块从右至左滚动显示字符"ABCDEFG1234567890"
    在这里插入图片描述

http://chatgpt.dhexx.cn/article/E1FkOOQZ.shtml

相关文章

涂鸦NBIOT OpenCPU开发快速入门(一)

今天我作为涂鸦的固件开发者的身份为大家详细讲解NB模组在涂鸦平台的快速对接。基于涂鸦完善的蜂窝通讯机制&#xff0c;使用涂鸦的OpenCPU SDK&#xff0c;可以实现真正的产品级对接&#xff01;用户只需要关注业务实现&#xff0c;无需过度关注底层基线逻辑以及物联网通讯流程…

nb-iot_IoT项目:Arduino使用Parse.com的Temboo向Android发送推送通知

nb-iot 这篇文章介绍了如何创建一个IoT项目&#xff0c;该项目使用Arduino通过Temboo和Parse.com将推送消息发送到Android智能手机。 例如&#xff0c;我们将构建一个基于Arduino和Android的警报系统&#xff0c;这是一个有趣的物联网(IoT)示例&#xff0c;该项目的目的是使用连…

NBIOT连接阿里云控制台(MQTT连接阿里云控制台)

首先使用MQTT工具连接阿里云平台进行测试之后再使用NBIOT连接控制台&#xff0c;这里主要讲解MQTT连接阿里云的步骤 1、注册或登录阿里云账号 自行前往阿里云官网注册 2、进入物联网界面 首先点击阿里云旁边1位置的选项进入如下界面&#xff0c;找到物联网IOt里面的物联网平…

NB-IoT 接入 5G 核心网丨边缘计算阅读周

#边缘计算阅读周# 读书的人&#xff0c;有梦可做。 边缘计算社区联合6大出版社邀您一起阅读&#xff0c;一起做追梦人。 在近日结束的ITU-R WP5D#35会议上&#xff0c;3GPP技术正式被接受为ITU IMT-2020 5G技术标准。 此次通过的3GPP技术包含中国提交的3GPP NR NB-IoT RIT&am…

NB-IOT开发实战

一&#xff0c;初识NB-IOT 1,NB-IOT介绍 NB ----Narrow BandIOT —Internet of thingsNB-IOT —窄带物联网 2&#xff0c;物联网发展 广/深覆盖&#xff1a;比GPRS覆盖增强20dB 低功耗&#xff1a;基于AA电池&#xff0c;使用寿命可超过10年 低成本&#xff1a;…

SIM7020X NB-IOT HAT 通过MQTT连接EMQ物联网平台

序言&#xff1a; MQTT是基于二进制消息的发布/订阅编程模式的消息协议&#xff1b;由于规范很简单&#xff0c;非常适合需要低功耗和网络带宽有限的IoT场景&#xff0c;比如&#xff1a;智能家居、智慧城市和医疗医护&#xff1b;深受广大童鞋的青睐和喜爱。下面我们以SIM7020…

NB-IOT接入云平台

概述&#xff1a; 在云平台创建一个NB-IOT的项目&#xff0c;启动模块&#xff0c;让模块能够接入云平台&#xff0c;通过云平台上报光照数据&#xff0c;在云平台控制相关执行器。 一、在云平台添加项目 二、添加设备 三、设备上电云平台上传传感器数据 四、设备可以通过KEY2…

NB-iot网络的组成架构

大家好&#xff0c;今天小白给大家简单介绍一下NB-iot网络的组成架构&#xff0c;欢迎一起交流学习。NB-iot网络架构.终端:主要是通过空口连接到基站。终端侧主要包含行业终端与NB-IoT模块。行业终端包括:芯片、模组、传感器接口、终端等;NB-IoT模块包括无线传输接口、软SIM装置…

【物联网】三大厂家NB-IOT卡对比

联通 联通没有集团统一的NB-IoT云平台,客户使用联通NB卡&#xff0c;设备数据无需再经过运营商平台&#xff0c;可直接接入自家服务器 收费 按月收费&#xff0c;30M/月&#xff0c;资费约一年15元 移动 参考网址&#xff1a;https://blog.csdn.net/Sanjay_Wu/article/deta…

Wifi模块-ESP-01s

Wifi模块-ESP-01s 蓝牙&#xff0c;ESP-01s&#xff0c;Zigbee&#xff0c;NB-lot等通信模块都是基于AT指令的设计 什么是AT指令&#xff1f; AT指令集是从终端设备&#xff08;Terminal Equipment&#xff0c;TE)或数据终端设备&#xff08;Data Terminal Equipment&#xff…

MySQL数据库(四)底层NB-IoT数据流的数据库写入

底层NB-IoT数据流的数据库写入 本文主要针对本人在NB-IoT项目中有关数据库的开发和使用&#xff0c;进行一些粗浅的学习指导。欢迎大家在评论区批评指正&#xff0c;感谢&#xff01; 文章目录 前言一、建立工程1.package:model2.package:dao3.package:util4.package:main 二、…

NB-LoT 云平台对接及使用

1、NB-LoT网络架构 1.1 NB-LoT网络框架 NB核心网络中的MME 提供核心网管理器&#xff0c;SGW提供核心网数据管理器&#xff0c;PGW核心网数据转发器 SCEE,SCS/AS是运行商自己部署的管理平台&#xff0c;主要用于NB模组&#xff0c;NB网络的管理&#xff0c;还会提供一些API&a…

STM32之NB-IoT学习(一)——NB-IoT介绍

这篇先总结一下NB-IoT的基本知识&#xff0c;下一篇再涉及相关单片机程序代码。 目录 一. NB-IoT概念及特点 1.概念 2.特点 3.目前主要应用情况 二. NB-IOT部署方式 1.独立部署&#xff08;Stand alone operation&#xff09;简称ST 2.保护带部署&#xff08;Guard ban…

OFDM载波间隔_NBloT上行子载波

相比LTE的上行物理信道,NB-IoT的上行物理信道可谓简化了很多,因此一些流程机制也改变很多。由于不需要在上行信道中传输CSI或者SR,因此在上行信道结构设计中也不需要专门保留上行控制共享信道。NB-IoT上行信道包含两种物理信道,一个是窄带物理上行共享信道(NPUSCH),另外一…

Tiny OS+nblot,值得程序员体验吗?

在之前《国产物联网操作系统大阅兵》等文章中笔者都曾立过flag&#xff0c;要为读者分享一下国产物联网平台的实际使用体验。而且由于近日亲身听过一场《区块链数字货币发展前景》的讲座&#xff0c;可是主讲人却连Libra的测试链都没亲身搭建过完&#xff0c;这种只能坐而言不能…

Bigdog

YouTube上可以找到不少视频。 http://www.youtube.com/watch?vcHJJQ0zNNOM

DOG简析

Difference of Gaussian(DOG)是高斯函数的差分。我们已经知道可以通过将图像与高斯函数进行卷积得到一幅图像的低通滤波结果&#xff0c;即去噪过程&#xff0c;这里的Gaussian和高斯低通滤波器的高斯一样&#xff0c;是一个函数&#xff0c;即为正态分布函数。 那么differenc…

Boston Dog

和一个北航的学弟聊到了波士顿动力这个公司&#xff0c;突然想做一期这个公司的介绍。很多人可能怎么听过这个公司&#xff0c;给出一张“狗狗”的照片&#xff0c;大家可能就会很熟悉了。 在B站上应该有很多关于这个狗狗的视频&#xff1a; https://www.bilibili.com/video/B…