当前位置: 首页 > news >正文

STM32-GPIO实践部分1-跑马灯实验

目录

目录

1.思路分析

🌵理论思路🌵

 🌵硬件设计🌵

🌵 代码思路🌵

方案1-库函数

方案2-寄存器(官方寄存器)

方案3-寄存器(寄存器地址)

2.代码实现

3.经验总结


1.思路分析

🌵理论思路🌵

使指定的GPIO端口引脚输出高/低电平,点亮LED灯,延迟,再熄灭LED,循环如此。

 🌵硬件设计🌵

  • 采用插件式的LED,原理是发光二极管,点亮条件是导通二极管,加正向导通电压。
  • 本次实验,采用LED正极接VCC,负极接GPIOB10,GPIOB11引脚,配置上拉,输出低电平点亮。

🌵 代码思路🌵

方案1-库函数

  • 使GPIOB10,GPIO11输出高低电平
    1. 开启GPIOB的时钟,GPIOB挂载在APB2总线上,调用RCC的ABP2使能函数
    2. 配置GPIOB10,11的模式,上拉输出,速度任意,调用GPIO的Init函数
    3. 输出高低电平,熄灭点亮,调用GPIO的SetBits函数和ResetBits函数。
  • 主函数内点亮,延迟,熄灭,点亮,循环下去

方案2-寄存器(官方寄存器)

该版本不需要stm官方提供的外设库函数和CM3内核提供的库函数,只需要官方进行寄存器地址宏定义的头文件,即stm32f10x.h,由于官方进行寄存器地址宏定义,我们只需要对宏定义后的地址名称进行操作。

  • 使GPIOB10,GPIO11输出高低电平
    1. 开启GPIOB的时钟,GPIOB挂载在APB2总线上,调用RCC的ABP2使能函数
    2. 配置GPIOB10,11的模式,上拉输出,速度任意,调用GPIO的Init函数
    3. 输出高低电平,熄灭点亮,调用GPIO的SetBits函数和ResetBits函数。
  • 主函数内点亮,延迟,熄灭,点亮,循环下去

方案3-寄存器(寄存器地址)

该版本不同之处在于,没有对地址进行宏定义,直接对寄存器的地址进行操作,所以就不需要官方的宏定义文件stm32f10x.h文件。至于跑马灯的实现思路与前者一样。

2.代码实现

库函数实现

//*****led.c*****
#include "led.h"
//跑马灯LED初始化函数
//1.开启连接LED的引脚端口所属的GPIOx时钟
//2.配置引脚端口的模式
void LED_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(LED_GPIOx_RCC,ENABLE);//GPIOB挂载在APB2总线GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//输出强有效的低电平GPIO_InitStruct.GPIO_Pin = LED_GPIO_Pin_1;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;GPIO_Init(LED_GPIOx,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//输出强有效的低电平GPIO_InitStruct.GPIO_Pin = LED_GPIO_Pin_2;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;GPIO_Init(LED_GPIOx,&GPIO_InitStruct);
}
//跑马灯LED置高电平
void LED_ON(void)
{GPIO_SetBits(LED_GPIOx,LED_GPIO_Pin_1 | LED_GPIO_Pin_2);
}
//跑马灯LED置低电平
void LED_OFF(void)
{GPIO_ResetBits(LED_GPIOx,LED_GPIO_Pin_1 | LED_GPIO_Pin_2);
}
//*****main.c*****
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
int main(void)
{LED_Init();while(1){LED_OFF();Delay_ms(500);LED_ON();Delay_ms(500);}
}

寄存器实现(官方)

#include "stm32f10x.h"
int main(void)
{while(1){//使用stm公司宏定义后的地址进行操作//规则:先FLASH,SRAM,PERIPH,再进行分类//AHB,APB1,APB2挂载在PERIPH上,外设再挂载在相应的总线上//外设下的寄存器,以结构体的形式挂载RCC->APB2ENR |= 1<<3; //APB2外设时钟使能寄存器,对应位置1开始外设GPIOB->CRH &= ~(0x0F<<(2*4));//端口配置高寄存器,Pin10配置清0GPIOB->CRH &= ~(0x0F<<(3*4));//端口配置高寄存器,Pin11配置清0GPIOB->CRH |= (0x01<<(2*4));//端口配置高寄存器,Pin10配置清0GPIOB->CRH |= (0x01<<(3*4));//端口配置高寄存器,Pin11配置清0//1.操作BSSR寄存器GPIOB->ODR &= ~(0x01<<10);//Pin10 = 0;数据输出寄存器ODR写低电平GPIOB->ODR &= ~(0x01<<11);//Pin11 = 0;数据输出寄存器ODR写低电平//		//2.操作BSSR寄存器
//		GPIOB->BSRR |= (1<<(10+16));//Pin10 = 0;位设置/清除寄存器,低16位置1,高16位置0
//		GPIOB->BSRR |= (1<<(11+16));//Pin11 = 0;
//		
//		//3.操作BRR寄存器
//		GPIOB->BRR |= (1<<10);//Pin10 = 0;位清除寄存器,低16位置0,高16位无效
//		GPIOB->BRR |= (1<<11);//Pin11 = 0;}}

寄存器实现(纯地址)

int main(void)
{while(1){//1.开启GPIOB的时钟*(unsigned int*)(0x40021000+0x18) |= (1<<3);//往APB2外设时钟控制寄存器中GPIOB对应的位写1//2.配置GPIO的模式*(unsigned int*)(0x40010C00+0x04) &= ~(0x0F<<(2*4));//将GPIOB的端口高配置寄存器对应的引脚清0*(unsigned int*)(0x40010C00+0x04) &= ~(0x0F<<(3*4));//GPIOB_pin10,pin11配置清0*(unsigned int*)(0x40010C00+0x04) |= (0x01<<(2*4));//将GPIOB的端口高配置寄存器对应的引脚配置为推挽输出*(unsigned int*)(0x40010C00+0x04) |= (0x01<<(3*4));//GPIOB_pin10,pin11配置为00 01推挽输出,速度10Mhz//3.输出低电平
//		*(unsigned int*)(0x40010C00+0x0C) &= ~(1<<10);//往ODR寄存器中设置清0
//		*(unsigned int*)(0x40010C00+0x0C) &= ~(1<<11);
//		*(unsigned int*)(0x40010C00+0x10) |= (1<<(10+16));//往BSRR寄存器的高16位中设置清0
//		*(unsigned int*)(0x40010C00+0x10) |= (1<<(11+16));//		*(unsigned int*)(0x40010C00+0x14) |= (1<<10);//往BRR寄存器的低16位中设置清0
//		*(unsigned int*)(0x40010C00+0x14) |= (1<<11);}}
void SystemInit(void)
{}

3.经验总结

  • 第一步都是开启时钟,每个外设都有其对应的时钟,时钟相关的内容就查阅RCC时钟这一章节的内容,不同的外设都查与之相对应的章节,在调用库函数时,根据所使用到外设,查看对应库函数头文件,一般函数声明放在最后(前面是一些宏定义),根据函数名称可大致知道其作用,将鼠标放在函数处可左击进行跳转定义,定义处有详细的英文注释函数作用,可结合翻译使用,函数的参数具体填什么,可以根据函数每次调用时使用到的断言函数进行跳转至宏定义处,都会注释该参数应当填入什么值。
  • 在使用纯地址进行操作时,第一步应都是查找参考手册,找到寄存器映射那一章节,可以看到外设的地址,在使用时将地址转化为指针类型的变量进行操作,操作时1位的写1写0使用或上1与上0进行实现,与上0为了保证其他位不变,其他位应是1,得到这个相与的数,通常采用改位为1其位为0的数取反得到。
http://www.dtcms.com/a/335211.html

相关文章:

  • 【Java基础面试题】Java基础概念
  • 按键及消抖
  • C++ 最短路Dijkstra
  • [Python]PTA:for 求奇数分之一序列前N项和
  • 安卓开发选择题
  • CUDA 编程笔记:CUDA延迟隐藏
  • 通配符 重定向 管道符
  • Java 中重载与重写的全面解析(更新版)
  • 在浏览器端使用 xml2js 遇到的报错及解决方法
  • BM25算法和传统的TF-IDF算法的区别
  • 改进版的QGIS 的(属性查询) identify featrues 功能
  • 算法题Day2
  • 计组-间接寻址
  • 抽象代数 · 代数结构 | 群、环、域、向量空间
  • 【QT】常⽤控件详解(八) Qt窗⼝ 菜单栏 工具栏 状态栏 浮动窗口 五种内置对话框
  • Oracle数据库文件管理与空间问题解决指南
  • Java中 23 种设计模式介绍,附带示例
  • IO流-打印流
  • leetcode hot100数组:缺失的第一个正数
  • 洛谷B3924 [GESP202312 二级] 小杨的H字矩阵
  • 洛谷B3865 [GESP202309 二级] 小杨的 X 字矩阵(举一反三)
  • CSDN部分内容改为视频转到B站-清单
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘opencv-python’问题
  • Cloudflare Tunnel 使用SAAS回源加速配置教程
  • 配置 Docker 镜像加速,解决 docker pull 拉取镜像失败、docker search 查询镜像失败等问题
  • Agent中的memory
  • 异构数据库兼容力测评:KingbaseES 与 MySQL 的语法・功能・性能全场景验证解析
  • MySQL性能优化:10个关键参数调整指南
  • ISO27001 高阶架构 之 支持 -2
  • 概率论基础教程第3章条件概率与独立性(三)