STM32拓展 低功耗案例1:睡眠模式 (register)

需求描述

让MCU进入睡眠模式,然后通过串口发送消息来唤醒MCU退出睡眠模式。观察LED在进入休眠模式后是否仍然开启。

思考

首先睡眠模式,唤醒的条件是中断,外部内部都可以,这里的串口接收中断时内部中断。

拓展:中断分为三大类:内核中断也叫异常,片上外设中断对于stem32来说也是内部所以叫内部中断,片外外设的中断stem32外部的中断,叫外部中断

图解:

软件设计:

设计到的寄存器:

ARM内核:

代码:

    /* 1. 设置普通睡眠模式 */
    SCB->SCR &= ~SCB_SCR_SLEEPDEEP;

usart.h

#ifndef __USART_H
#define __USART_H

#include "stm32f10x.h"
#include <stdio.h>

// 初始化
void USART_Init(void);

// 发送一个字符
void USART_SendChar(uint8_t ch);

// 接收一个字符
uint8_t USART_ReceiveChar(void);

// 发送字符串
void USART_SendString(uint8_t * str, uint8_t size);

// 接收字符串
void USART_ReceiveString(uint8_t buffer[], uint8_t *size);

#endif

usart.c

之前的代码新增3.4和4以及中断服务程序。

#include "usart.h"

// 初始化
void USART_Init(void)
{
    // 1. 开启时钟
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

    // 2. GPIO 工作模式
    // 2.1 PA9 - TX,复用推挽输出,CNF = 10,MODE = 11
    GPIOA->CRH |= GPIO_CRH_MODE9;
    GPIOA->CRH |= GPIO_CRH_CNF9_1;
    GPIOA->CRH &= ~GPIO_CRH_CNF9_0;
    // 2.2 PA10 - RX,浮空输入,CNF = 01,MODE = 00
    GPIOA->CRH &= ~GPIO_CRH_MODE10;
    GPIOA->CRH &= ~GPIO_CRH_CNF10_1;
    GPIOA->CRH |= GPIO_CRH_CNF10_0;

    // 3. 串口模块配置
    // 3.1 设置波特率 115200
    USART1->BRR = 0x271;

    // 3.2 使能串口和收发模块
    USART1->CR1 |= USART_CR1_UE;
    USART1->CR1 |= (USART_CR1_TE | USART_CR1_RE);

    // 3.3 配置数据帧的格式
    USART1->CR1 &= ~USART_CR1_M;    // 长度为 8 位
    USART1->CR1 &= ~USART_CR1_PCE;  // 不使用校验位
    USART1->CR2 &= ~USART_CR2_STOP; // 1 位停止位



    // 3.4 开启串口接收中断
    USART1->CR1 |= USART_CR1_RXNEIE;

    // 4. NVIC配置
    NVIC_SetPriorityGrouping(3);
    NVIC_SetPriority(USART1_IRQn, 3);
    NVIC_EnableIRQ(USART1_IRQn);
}

// 发送一个字符
void USART_SendChar(uint8_t ch)
{
    // 判断 TDR 是否为空,必须等待 TDR 为空才能继续发送
    while ((USART1->SR & USART_SR_TXE) == 0)
    {
    }

    // 将要发送的数据写入TDR
    USART1->DR = ch;
}

// 接收一个字符
uint8_t USART_ReceiveChar(void)
{
    // 判断 RDR 是否非空,必须等待 RDR 有数据才能读取出来
    while ((USART1->SR & USART_SR_RXNE) == 0)
    {
    }

    // 读取接收到的数据,返回
    return USART1->DR;
}

// 发送字符串
void USART_SendString(uint8_t *str, uint8_t size)
{
    for (uint8_t i = 0; i < size; i++)
    {
        USART_SendChar(str[i]);
    }
}

// 接收字符串
void USART_ReceiveString(uint8_t buffer[], uint8_t *size)
{
    // 定义变量,保存当前接收到的字符个数
    uint8_t i = 0;

    // 不停地接收字符,直到检测到空闲帧

    // 错误写法:
    // while ( (USART1->SR & USART_SR_IDLE) == 0 )
    // {
    // 	buffer[i] = USART_ReceiveChar();
    // 	i++;
    // }

    // 正确写法:
    // 外层循环:不停读取下一个字符
    while (1)
    {
        // 内层循环:判断当前数据帧是否结束
        while ((USART1->SR & USART_SR_RXNE) == 0)
        {
            // 一旦已经检测到空闲帧,就立刻退出
            if (USART1->SR & USART_SR_IDLE)
            {
                *size = i;
                USART1->DR;
                return;
            }
        }
        buffer[i] = USART1->DR;
        i++;
    }
}

// 重写fputc函数
int fputc(int ch, FILE * file)
{
    USART_SendChar(ch);
    return ch;
}

// 中断服务程序
void USART1_IRQHandler(void)
{
    if (USART1->SR & USART_SR_RXNE)
    {
        // 读取接收到的数据,清除标志位
        uint8_t c = USART1->DR & 0xff;

        USART_SendChar(c);
    }
}

main.c

前面有__的命令,证明时底层的命令,汇编指令。

#include "usart.h"
#include "delay.h"
#include "led.h"

void enter_sleep_mode(void);

int main(void)
{
	// 初始化
	USART_Init();
	LED_Init();

	printf("低功率实验:睡眠模式...\n");

	// 1. 开启LED灯,延时2s,模拟正常程序执行过程
	LED_On(LED_1);
	Delay_s(2);

	while (1)
	{
		// 2. 进入睡眠模式
		printf("正常代码执行完毕,3s后进入睡眠模式...\n");
		Delay_s(3);
		printf("进入睡眠模式");
		enter_sleep_mode();

		// 3. 以下代码只有在唤醒之后才会执行
		printf("从睡眠模式中唤醒...\n");
		Delay_s(2);
	}
}

// 定义进入睡眠模式的函数
void enter_sleep_mode(void)
{
	// 1. 设置普通睡眠模式(默认)
	SCB->SCR &= ~SCB_SCR_SLEEPDEEP;

	// 2. 使用WFI指令,进入睡眠模式
	__WFI();
}

led.h

#ifndef __LED_H
#define __LED_H

#include "stm32f10x.h"

// 宏定义LED灯
#define LED_1 GPIO_ODR_ODR0
#define LED_2 GPIO_ODR_ODR1
#define LED_3 GPIO_ODR_ODR8

// 初始化
void LED_Init(void);

// 开关LED灯
void LED_On(uint16_t led);
void LED_Off(uint16_t led);

// 翻转LED灯状态
void LED_Toggle(uint16_t led);

// 控制所有LED灯的开关
void LED_OnAll(uint16_t leds[], uint8_t size);
void LED_OffAll(uint16_t leds[], uint8_t size);

#endif

led.c

#include "led.h"

// 初始化
void LED_Init(void)
{
    // 1. 时钟配置,打开GPIOA时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

    // 2. 工作模式配置,PA0、PA1、PA8 通用推挽输出,CNF = 00,MODE = 11
    GPIOA->CRL |= GPIO_CRL_MODE0;
    GPIOA->CRL &= ~GPIO_CRL_CNF0;
    GPIOA->CRL |= GPIO_CRL_MODE1;
    GPIOA->CRL &= ~GPIO_CRL_CNF1;
    GPIOA->CRH |= GPIO_CRH_MODE8;
    GPIOA->CRH &= ~GPIO_CRH_CNF8;

    // 3. 初始状态所有引脚输出高电平,关灯
    LED_Off(LED_1);
    LED_Off(LED_2);
    LED_Off(LED_3);
}

// 开关LED灯
void LED_On(uint16_t led)
{
    GPIOA->ODR &= ~led;
}
void LED_Off(uint16_t led)
{
    GPIOA->ODR |= led;
}

// 翻转LED灯状态
void LED_Toggle(uint16_t led)
{
    // 根据IDR对应位的值,判断当前LED状态
    if ((GPIOA->IDR & led) == 0)
    {
        LED_Off(led);
    }
    else
    {
        LED_On(led);
    }
}

// 控制所有LED灯的开关
void LED_OnAll(uint16_t leds[], uint8_t size)
{
    for (uint8_t i = 0; i < size; i++)
    {
        LED_On(leds[i]);
    }
}
void LED_OffAll(uint16_t leds[], uint8_t size)
{
    for (uint8_t i = 0; i < size; i++)
    {
        LED_Off(leds[i]);
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue 基础参数增加多语言配置

js 对数组的增删改查 字段在数据库存储为nvarchar &#xff0c;varchar存储波斯语会乱码 数组格式&#xff1a; {"en": [{"type": "10","value": "Confirm","color": ""},{"type": "…

[桌面运维]windows自动设置浅深色主题

设置自动浅色/深色主题 我看很多up主的教程过于繁琐&#xff0c;需要添加四个功能&#xff0c;并且有些还不能生效&#xff01; 大多数都是教程&#xff1a; 自动任务栏浅色 add HKCUSOFTWAREMicrosoftWindowsCurrentVersionThemesPersonalize/v SystemUsesLightTheme /t …

[ubuntu-22.04]ubuntu不识别rtl8153 usb转网口

问题描述 ubuntu22.04插入rtl8153 usb转网口不识别 解决方案 安装依赖包 sudo apt-get install libelf-dev build-essential linux-headers-uname -r sudo apt-get install gcc-12 下载源码 Realtek USB FE / GBE / 2.5G / 5G Ethernet Family Controller Softwarehttps:/…

基于Python的考研学习系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

图漾相机基础操作

1.客户端概述 1.1 简介 PercipioViewer是图漾基于Percipio Camport SDK开发的一款看图软件&#xff0c;可实时预览相机输出的深度图、彩色图、IR红外图和点云图,并保存对应数据&#xff0c;还支持查看设备基础信息&#xff0c;在线修改gain、曝光等各种调节相机成像的参数功能…

Yocto 项目中的包管理系统详细解析

1. 包管理系统概念 包管理系统是用于管理软件包的工具和机制&#xff0c;包括创建、分发和安装软件包。Yocto 项目支持以下三种主要的包管理系统及其相关包格式&#xff1a; IPK (Itsy Package System)&#xff1a;适合轻量级嵌入式应用&#xff0c;通过 OPKG 管理。RPM (Red…

RISC-V学习笔记

1.RISC ISA1个基本整数指令集多个可选的扩展指令集&#xff0c;如RV32I表示支持32位整数指令集。I表示基本指令集&#xff0c;M表示整数乘法与除法指令集&#xff0c;A表示存储器原子指令集&#xff0c;F表示单精度浮点指令集&#xff0c;D表示双精度浮点指令集等&#xff0c;C…

第四届计算机、人工智能与控制工程

第四届计算机、人工智能与控制工程 The 4th International Conference on Computer, Artificial Intelligence and Control Engineering 重要信息 大会官网&#xff1a;www.ic-caice.net 大会时间&#xff1a;2025年1月10-12日 大会地点&#xff1a;中国合肥 (安徽大学磬苑…

Docker安装易有云(casaos安装易有云)

无法拉取易有云&DDNSTO Docker镜像&#xff1f; 官方视频 Docker方式安装易有云&#xff0c;包括并不限于Unraid/爱快/群晖等&#xff0c;只要有Docker的设备都成&#xff0c;包括一些Linux发行版等。 铁威马&#xff1a;首先在应用中心里安装Docker(TOS 4.0及更高的系统…

【计算机视觉技术 - 人脸生成】2.GAN网络的构建和训练

GAN 是一种常用的优秀的图像生成模型。我们使用了支持条件生成的 cGAN。下面介绍简单 cGAN 模型的构建以及训练过程。 2.1 在 model 文件夹中新建 nets.py 文件 import torch import torch.nn as nn# 生成器类 class Generator(nn.Module):def __init__(self, nz100, nc3, n…

手机投屏到电视的3种选择:无线本地投屏,无线远程投屏,AirPlay投屏

现在大部分手机投屏都要求连接相同的WiFi&#xff0c;这就意味着手机投屏到电视必须是近距离投屏&#xff0c;稍微远一点就会脱离WiFi连接范围&#xff0c;投屏失败。 如果想将手机远程投屏到安卓电视&#xff0c;要怎样做&#xff1f; 第一步&#xff0c;在手机和安卓电视都安…

zookeeper 数据类型

文章目录 引言I Znodezonde stat (状态信息)znode类型临时\永久序列化特性引言 在结构上与标准文件系统非常类似,拥有一个层次的命名空间,都是采用树形层次结构 Zookeeper树中的每个节点被称为:Znode,没有文件和目录之分。Znode兼具文件和目录两种特点Znode存储数据大小有…

73 mysql replication 集群的交互

前言 新建两个数据库, 分别为 192.168.220.132:3001, 192.168.220.132:3002 设置 192.168.220.132:3001 为 master, 192.168.220.132:3002 为 slave 配置文件如下 然后使用 mysqld --initialize 来初始化 data 目录, 以及相关基础数据库 这里会为 root 账户创建一个随机的…

CG顶会论文阅读|《科技论文写作》硕士课程报告

文章目录 一、基本信息1.1 论文基本信息1.2 课程基本信息1.3 博文基本信息 二、论文评述&#xff08;中英双语&#xff09;2.1 研究问题&#xff08;Research Problem&#xff09;2.2 创新点&#xff08;Innovation/Contribution&#xff09;2.3 优点&#xff08;Why this pape…

路由器的转发表

【4-24】 已知路由器R₁ 的转发表如表T-4-24 所示。 表T-4-24 习题4-24中路由器R₁的转发表 前缀匹配 下一跳地址 路由器接口 140.5.12.64/26 180.15.2.5 m2 130.5.8/24 190.16.6.2 ml 110.71/16 ----- m0 180.15/16 ----- m2 190.16/16 ----- ml 默认 11…

嵌入式驱动开发详解8(阻塞/非阻塞/异步通信)

文章目录 前言阻塞非阻塞异步通知后续 前言 首先来回顾一下“中断”&#xff0c;中断是处理器提供的一种异步机制&#xff0c;我们配置好中断以后就 可以让处理器去处理其他的事情了&#xff0c;当中断发生以后会触发我们事先设置好的中断服务函数&#xff0c; 在中断服务函数…

【MATLAB第112期】基于MATLAB的SHAP可解释神经网络回归模型(敏感性分析方法)

【MATLAB第112期】基于MATLAB的SHAP可解释神经网络回归模型&#xff08;敏感性分析方法&#xff09; 引言 该文章实现了一个可解释的神经网络回归模型&#xff0c;使用BP神经网络&#xff08;BPNN&#xff09;来预测特征输出。该模型利用七个变量参数作为输入特征进行训练。为…

DeepSeek-V3 正式发布,已在网页端和 API 全面上线,性能领先,速度飞跃。

DeepSeek-V3 在推理速度上相较历史模型有了大幅提升。在目前大模型主流榜单中&#xff0c;DeepSeek-V3 在开源模型中位列榜首&#xff0c;与世界上最先进的闭源模型不分伯仲。 简介 DeepSeek-V3是一个强大的混合专家 (MoE) 语言模型&#xff0c;总共有 671B 个参数&#xff0c;…

深度评测uni-app x:开启跨平台开发新篇章

文章目录 一、引言1.1 跨平台开发的崛起1.2 uni-app x 初印象 二、uni-app x 核心特性评测2.1 uts 语言&#xff1a;跨平台编程新利器2.2 uvue 渲染引擎&#xff1a;原生渲染新体验2.3 强大的组件和 API 支持2.4 插件生态&#xff1a;拓展无限可能 三、与 uni-app 对比&#xf…

用python编写一个放烟花的小程序

import pygame import random # 代码解释及使用说明&#xff1a; # 首先&#xff0c;导入 pygame 和 random 库。pygame 用于创建游戏窗口和图形绘制&#xff0c;random 用于生成随机数。 # 初始化 pygame&#xff0c;并设置屏幕尺寸为 800x600 像素&#xff0c;设置窗口标题为…