文章目录

  • 前言
  • 一、相关寄存器配置介绍
    • 1.相关寄存器配置介绍
  • 二、使用寄存器点亮LED灯
    • 1.工程模板的建立
    • 2.配置GPIO端口
    • 3.主要函数
    • 4.编译生成HEX文件
    • 5.电路搭建
  • 三、STM32的开发环境的搭建
    • 1.安装STM32CubeMX
    • 2.安装固件库
    • 3.进行仿真实验
    • 4.MDK5模拟示波器
  • 四、小结

前言

1.学习和理解STM32F103系列芯片的地址映射和寄存器映射原理;了解GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)。
2.用 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED,并搭建了电路,分别GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚上控制LED灯(最高时钟2Mhz),轮流闪烁,间隔时长1秒。
3.安装 stm32CubeMX,用cubemx完成初始化过程,采用HAL库编程实现。
4.在Keil下用软件仿真运行上面代码,并用虚拟逻辑分析仪观察 对应管脚上的输出波形(高低电平转换),看是否是1秒的周期。

一、相关寄存器配置介绍

1.相关寄存器配置介绍

不管是库函数操作还是HAL操作,本质上都是对寄存器的操作。
在提供的“ STM32F103中文教程及参考手册”中看到GPIO寄存器7种类型,首先看下5.2.1端口配置低寄存器,通过该寄存器具体介绍下。
先解释下(GPIOx_CRL)(x=A…E)的意思。stm32f103引脚有多有少,多则144个,少则48个(本实验用的48脚芯片),所以会把这些引脚分成组,A、B、C、D…每组最多16个引脚,注意,是最多,并不是一定要有16个引脚!

48引脚的单片机只分成了A、B、C、D(PA、PB、PC、PD)组。GPIO英语的全称是General-purpose input/output,翻译过来就是通用的IO口。GPIOA_CRL的意思是控制A口的CRL寄存器。再回到上面的CTRL寄存器图,“偏移地址0x00”。那么偏移是相对于谁偏移的,应该有个基准!先给大家举个例子,要盖一幢商务大楼,外面盖完了如果里面是空的,是不行的,所以要盖一层层,一层层盖了也不行,在每一层隔处一个个房间,这样一幢商务大楼才能使用。我们单片机内存也是,整一大块是不能用的,也要隔成一个个房间才能使用,每个房间相当于寄存器,要么有人(相当于为1),要么没人(相当于为0)。所以要查下GPIOC安排在几楼!

在提供的手册中(P18页)可以看到GPIOC的地址范围是0x4001 1000~0x4001 13FF。所以它的起始地址是0x4001 1000,也就是基地址!偏移0x00后可以得出GPIOC->CRL的地址(GPIOC端口的起始地址+偏移地址)为0x40011000。
所谓的复位值,就是指如果没有操作这个寄存器时,寄存器存放的默认值。复位值按位拆分0x4 = 0b0100,0x表示16进制,0b表示二进制,也就是默认CNF 01,MODE 00,是浮空输入。

再回到CTRL寄存器图,看下面的图。一共有32个位,0~31,也就是CTRL寄存器有32位,这也是为什么叫做stm32的原因,以前的51单片机是8位单片机也就是一次性最多能处理8个位。
看红色框部分(0-3位),CNF0和MODE0。再看4-7位,CNF1和MODE1。说明GPIOC中的第0位需要CNF0和MODE0这4个位来控制,GPIOC中的第1位需要CNF1和MODE1这4个位来控制。具体可以控制哪些呢,在往下看。
在上图中,以MODE0为例,占了两个位,每个位可以表示0或1,所以可以表示4种情况!一般情况下是输出模式,在下表中的MODEy[1:0]就可以看到③,有输出和输入模式,本次实验就是选择“10”表示输出模式,最大速度为2MHZ,再去看CNFy[1:0],根据输入输出的不同有不同的选择,那么我们刚才选的是输出模式,所以看②,选择“00”,表示“通用推挽输出模式”。
通过以下代码实现通用推挽输出模式:

GPIOC_CRH &= ~(0x0F<<(4*5));
GPIOC_CRH |= (1<<(4*5));

再看5.2.3和5.2.4,一个用于配置输入,一个用于配置输出,那么我们看输出。
因为每个GPIO组只有16个引脚,所以ODR寄存器只用了低16位,高16位保留。
这个寄存器功能很简单,控制输出的数据为0或者1 。
所以我们控制LED延时闪烁也很简单,就是控制ODR寄存器先输出1,LED灯亮,延时一段时间,控制ODR寄存器先输出0,LED灯灭,一直循环,就能实现流水灯的效果。
代码如下:

GPIOC_ODR &= ~(1<<13);//配置输出低电平0
GPIOC_ODR |= (1<<13);//配置输出高电平1

二、使用寄存器点亮LED灯

1.工程模板的建立

stm32提供了一个用c语言封装好的固件库,我们要实现什么功能,直接调用相应的库函数即可。
要使用ST固件库,可以建立一个工程模板,方便我们调用函数。

2.配置GPIO端口

GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。
GPIO端口的初始化设置三步骤:
a.时钟配置
b.输入输出模式设置
c.最大速率设置
库函数中提供了一个结构体来配置GPIO端口的输入输出模式设置 、 最大速率设置等。
定义的结构体如下:

// @file    stm32f10x_gpio.h
typedef struct
{uint16_t GPIO_Pin;           /*!< 选择要配置的 GPIO 引脚 */GPIOSpeed_TypeDef GPIO_Speed;  /*!< 选择 GPIO 引脚的速率 */GPIOMode_TypeDef GPIO_Mode;    /*!< 选择 GPIO 引脚的工作模式 */
}GPIO_InitTypeDef;

这个结构体中包含了初始化 GPIO 所需要的信息,包括引脚号、工作模式、输出速率。
设计这个结构体的思路是:初始化 GPIO 前,先定义一个这样的结构体变量,根据需要配置 GPIO 的模式,对这个结构体的各个成员进行赋值,然后把这个变量作为“GPIO 初始化函数”的输入参数,该函数能根据这个变量值中的内容去配置寄存器,从而实现 GPIO 的初始化。
配置 端口位为通用推挽输出,速度为 2M

GPIO_InitTypeDef   GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;             //输出模式为通用推挽输出
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4 ;                    //选定输出端口为GPIO_Pin_4
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;              //输出速度为2MGPIO_Init(GPIOA,&GPIO_InitStruct);

至此一个GPIOB_Pin_4配置完毕,我们总算可以控制一个 LED 了。

3.主要函数

led.h函数

#ifndef _LED_H
#define _LED_H#include "stm32f10x.h"
void LED_R_TOGGLE(void);
void LED_G_TOGGLE(void);
void LED_Y_TOGGLE(void);
void LED_Init(void);
#endif

led.c函数

#include "led.h"
#include "delay.h"void LED_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);  //打开外设GPIOB的时钟GPIO_InitTypeDef   GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;             //输出模式为通用推挽输出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4 ;             //选定端口为GPIO_Pin_4GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;               //输出速度为2MGPIO_Init(GPIOA,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;              //输出模式为通用推挽输出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10 ;             //选定端口为GPIO_Pin_1GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;              //输出速度为2MGPIO_Init(GPIOB,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;              //输出模式为通用推挽输出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_14 ;             //选定端口为GPIO_Pin_14GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;             //输出速度为2MGPIO_Init(GPIOC,&GPIO_InitStruct);
}void LED_R_TOGGLE(void)
{GPIO_SetBits(GPIOA, GPIO_Pin_4);delay_ms(500);GPIO_ResetBits(GPIOA,GPIO_Pin_4);
}
void LED_G_TOGGLE(void)
{GPIO_SetBits(GPIOB, GPIO_Pin_10);delay_ms(500);GPIO_ResetBits(GPIOB,GPIO_Pin_10);
}
void LED_Y_TOGGLE(void)
{GPIO_SetBits(GPIOC, GPIO_Pin_14);  delay_ms(500);GPIO_ResetBits(GPIOC,GPIO_Pin_14);
}

delay.h函数

#ifndef __DELAY_H
#define __DELAY_H
#include "sys.h"void delay_init(void);
void delay_ms(u16 nms);
void delay_us(u32 nus);#endif

delay.c函数
本实验调用的是正点原子写好的延时函数用于实现延时1s后三种LED灯轮流闪烁

#include "delay.h"
//
//如果需要使用OS,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"                   //ucos 使用
#endifstatic u8  fac_us=0;                         //us延时倍乘数
static u16 fac_ms=0;                           //ms延时倍乘数,在ucos下,代表每个节拍的ms数#if SYSTEM_SUPPORT_OS                            //如果SYSTEM_SUPPORT_OS定义了,说明要支持OS了(不限于UCOS).
#ifdef  OS_CRITICAL_METHOD                      //OS_CRITICAL_METHOD定义了,说明要支持UCOSII
#define delay_osrunning     OSRunning           //OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec OS_TICKS_PER_SEC    //OS时钟节拍,即每秒调度次数
#define delay_osintnesting  OSIntNesting        //中断嵌套级别,即中断嵌套次数
#endif//支持UCOSIII
#ifdef  CPU_CFG_CRITICAL_METHOD                 //CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII
#define delay_osrunning     OSRunning           //OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec OSCfg_TickRate_Hz   //OS时钟节拍,即每秒调度次数
#define delay_osintnesting  OSIntNestingCtr     //中断嵌套级别,即中断嵌套次数
#endif//us级延时时,关闭任务调度(防止打断us级延迟)
void delay_osschedlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD                  //使用UCOSIIIOS_ERR err; OSSchedLock(&err);                            //UCOSIII的方式,禁止调度,防止打断us延时
#else                                           //否则UCOSIIOSSchedLock();                                //UCOSII的方式,禁止调度,防止打断us延时
#endif
}//us级延时时,恢复任务调度
void delay_osschedunlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD                  //使用UCOSIIIOS_ERR err; OSSchedUnlock(&err);                      //UCOSIII的方式,恢复调度
#else                                           //否则UCOSIIOSSchedUnlock();                          //UCOSII的方式,恢复调度
#endif
}//调用OS自带的延时函数延时
//ticks:延时的节拍数
void delay_ostimedly(u32 ticks)
{
#ifdef CPU_CFG_CRITICAL_METHODOS_ERR err; OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);    //UCOSIII延时采用周期模式
#elseOSTimeDly(ticks);                          //UCOSII延时
#endif
}//systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{    if(delay_osrunning==1)                      //OS开始跑了,才执行正常的调度处理{OSIntEnter();                           //进入中断OSTimeTick();                        //调用ucos的时钟服务程序               OSIntExit();                             //触发任务切换软中断}
}
#endif//初始化延迟函数
//当使用OS的时候,此函数会初始化OS的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init()
{
#if SYSTEM_SUPPORT_OS                           //如果需要支持OS.u32 reload;
#endifSysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟  HCLK/8fac_us=SystemCoreClock/8000000;              //为系统时钟的1/8
#if SYSTEM_SUPPORT_OS                           //如果需要支持OS.reload=SystemCoreClock/8000000;                //每秒钟的计数次数 单位为M  reload*=1000000/delay_ostickspersec;      //根据delay_ostickspersec设定溢出时间//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右   fac_ms=1000/delay_ostickspersec;           //代表OS可以延时的最少单位    SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;       //开启SYSTICK中断SysTick->LOAD=reload;                        //每1/delay_ostickspersec秒中断一次   SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;       //开启SYSTICK    #elsefac_ms=(u16)fac_us*1000;                    //非OS下,代表每个ms需要的systick时钟数
#endif
}                                    #if SYSTEM_SUPPORT_OS                           //如果需要支持OS.
//延时nus
//nus为要延时的us数.
void delay_us(u32 nus)
{        u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD;                  //LOAD的值             ticks=nus*fac_us;                           //需要的节拍数             tcnt=0;delay_osschedlock();                      //阻止OS调度,防止打断us延时told=SysTick->VAL;                            //刚进入时的计数器值while(1){tnow=SysTick->VAL; if(tnow!=told){        if(tnow<told)tcnt+=told-tnow;       //这里注意一下SYSTICK是一个递减的计数器就可以了.else tcnt+=reload-tnow+told;     told=tnow;if(tcnt>=ticks)break;              //时间超过/等于要延迟的时间,则退出.}  };delay_osschedunlock();                       //恢复OS调度
}
//延时nms
//nms:要延时的ms数
void delay_ms(u16 nms)
{    if(delay_osrunning&&delay_osintnesting==0)  //如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)     {         if(nms>=fac_ms)                           //延时的时间大于OS的最少时间周期 { delay_ostimedly(nms/fac_ms);       //OS延时}nms%=fac_ms;                           //OS已经无法提供这么小的延时了,采用普通方式延时    }delay_us((u32)(nms*1000));                   //普通方式延时
}
#else //不用OS时
//延时nus
//nus为要延时的us数.
void delay_us(u32 nus)
{        u32 temp;             SysTick->LOAD=nus*fac_us;                    //时间加载           SysTick->VAL=0x00;                           //清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;   //开始倒数    do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));       //等待时间到达   SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;   //关闭计数器SysTick->VAL =0X00;                         //清空计数器
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{                  u32 temp;         SysTick->LOAD=(u32)nms*fac_ms;               //时间加载(SysTick->LOAD为24bit)SysTick->VAL =0x00;                           //清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;   //开始倒数  do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));     //等待时间到达   SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;   //关闭计数器SysTick->VAL =0X00;                        //清空计数器
}
#endif

main.c函数

#include  "stm32f10x.h"
#include "delay.h"
#include "led.h"
int main(void)
{              LED_Init();  delay_init();                  //使用系统滴答定时器、延时初始化while(1)                       //循环亮起{LED_R_TOGGLE();delay_ms(500);             //红灯亮后延时1sLED_G_TOGGLE();delay_ms(500);             //绿灯亮后延时1sLED_Y_TOGGLE();delay_ms(500);             //黄灯亮后延时1s}
}

4.编译生成HEX文件

击左上角的编译按钮进行编译,可以看到生成了hex 文件
打开建立的OBJ文件夹也可以看见存放有生成的.hex文件

5.电路搭建

本次实验是在面包板上使用c8t6来控制红、绿、黄三个灯轮流闪烁,因此需熟悉面包板的使用。电路图如下所示:

其中实验用到的STM32 开发板用的 USB 转串口的驱动芯片是 CH340,要使用串口得先在电脑中安装 USB 转串口驱动—CH340 版本,下载链接详见前面。

如果 USB 转串口驱动安装成功,USB 线跟板子连接没有问题,在计算机->管理->设备管理器->端口中可识别到串口。

用 USB 线连接电脑和开发板的 USB 转串口接口:USB TO UART,给开发板上电。
打开 mcuisp 软件,配置如下:
①搜索串口,设置波特率 115200(尽量不要设置的太高)
②选择要下载的HEX 文件
③校验、编程后执行
④DTR 低电平复位,RTS 高电平进入 bootloader
⑤开始编程,如果出现一直连接的情况,按一下开发板的复位键即可

开始编译后的下载成功后的提示如下图,则说明HEX文件已经成功被烧录到芯片中。

然后流水灯将会正常轮流闪烁。

三、STM32的开发环境的搭建

1.安装STM32CubeMX

由于STM32CubeMX是Java实现的,需要安装jdk环境。下载地址:
https://www.st.com/en/development-tools/stm32cubemx.html
安装过程:
进入下载界面,根据自己的需要下载对应的版本,找到下载路径,对下载的zip压缩包进行解压,进入解压到的文件夹,点击右键以管理员身份运行SetupSTM32CubeMX-6.3.0-Win.exe,进入到下面的界面,点击next,点击"I accept the terms of this license agreement",接着选择Next,在跳出的页面,点击Next,进行安装,点击Done就安装完成了。

2.安装固件库

运行STM32CubeMX程序,选择 Help->Manage embedded software packages 安装固件库,根据自己的芯片类型,选择一个固件库,点击下方的From Local…进行下载,表示从本地安装(已经在本地下载了对应的固件库),Install now是通过网络下载,我这里选择的是在线安装。
前面的框显示为绿色,表示下载成功,安装MDK5软件
具体安装请参照下面链接:
https://blog.csdn.net/qq_43279579/article/details/108880667

3.进行仿真实验

至此完成了cubemx初始化过程,然后用其进行流水灯的仿真,进入刚刚选择的路径,打开MDK-ARM子文件夹,通过keil打开刚刚生成的项目。
通过目录找到并打开main.c文件,找到主函数int main(void)那一部分
如果要在STM32CubeMX生成的工程中添加代码,要在提示 /* USER CODE BEGIN* /和/* USER CODE END*/之间添加代码,这样STM32CubeMX重新生成代码时才不会将自己添加的代码删除掉。此外,注意使用CubeMX配置生成的工程中的注释最好不要随便删除掉。
在while循环的/* USER CODE BEGIN 3 /和/ USER CODE END 3 */之间插入以下代码:
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);//PA4亮灯
HAL_Delay(500);//延时0.5s
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
HAL_Delay(500);//延时0.5s

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);//PB10亮灯
HAL_Delay(500);//延时0.5s
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET);//PB10熄灯
HAL_Delay(500);//延时0.5sHAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);//PC14亮灯
HAL_Delay(500);//延时0.5s
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC14熄灯
HAL_Delay(500);//延时0.5s


编译运行程序无报错且生成相应的.hex文件
在文件夹MDK-ARM下,打开与工程名相同的子文件夹可以看到生成的.hex文件
然后程序烧录过程如上述步骤所示,最终完成用HAL库编程实现流水灯的实验。

4.MDK5模拟示波器

在没有示波器条件下,可以使用MDK5的软件仿真逻辑分析仪功能观察管脚的时序波形,更方便动态跟踪调试和定位代码故障点,因此可以用MDK5的软件仿真观察3个GPIO端口的输出波形。
1.设置options for target

Target的设置:
Target界面中,选择正确的晶振大小,我使用的是8MHz的外部晶振。这个选项在软件仿真中起到很重要的作用,如果选择错误,那么波形一定是错误的,因为时间不准确。不过这个参数只在软件仿真中起作用,当程序在硬件中运行并没有影响。
Dubug的设置:
首先应该选择Use Simulator,其次是Run to main()选项打√,然后分别修改上图中的 4和5处,注意,DARMSTM.DLL和TARMSTM.DLL在STM32的单片机中应该都是固定的,Paramter是跟所采用的具体芯片是对应的,应与Target中STMicroelectronics 保持一致。
2.参数设置完毕,点击Debug,进入调试界面

3.选择逻辑分析仪Logic Analyer
4.选择要观察的引脚
①点击Setup Logic Analyzer
②添加要观察的引脚
(引脚添加:如PA4可直接输入PORTA.4即可)
图中选择的三个引脚分别是PA4、PB10和PC14,GPIOA对应的为PORTA,那么GPIOB对应的也应该写成PORTB,以此类推。其中PORTA & 0x00001000后再右移4位也就把PA4的状态获取出来,1就是高电平,0就
是低电平。PB10和PC14同理。一定要选择Bit,颜色是为了区分不同的引脚,根据需要配置即可。设置完成后退
出,就可以在后续的操作中观察到波形。
注意:如果上述步骤1中的Debug中的4、5没有正确设置,那么在添加引脚的时候就会出现报错:Unknown Signal !
5.运行程序

6.观察波形,把光标移动到逻辑分析仪显示波形的区域,上下滚动滑轮,就可以放大和缩小波形
这样就可以直观的看出各个引脚的波形图,从而知道它们的区别。

四、小结

使用STM32CubeMX自动生成代码并点亮LED灯是非常简单的,通过这次实验,让我明白了合理使用工具的“快乐”,能使我们更快的编写代码,提高工作效率。在日常工作中,逻辑分析仪和示波器是MCU工程师必不可少的工具,有时候程序有BUG的时候就需要用到这些工具看波形,从而更快地定位到问题所在,进而解决问题。keil的软件仿真功能中的逻辑分析仪在这个时候就是一个不错的选择。

用寄存器HAL库完成LED流水灯程序以及通过MDK5模拟示波器观察波形相关推荐

  1. 用寄存器HAL库完成LED流水灯程序

    重庆交通大学信息科学与工程学院 <嵌入式系统开发>课程 作业报告(第4周) 班 级: 通信工程2001 姓名-学号 : 阎桂董-632007030622 实验项目名称: 作业题目 实验项目 ...

  2. STM32Cubemx的安装及用寄存器HAL库完成LED流水灯程序

    目录 一.STM32CubeMx安装 (一)简介 (二)下载地址 1.官方下载地址 2.网盘下载地址 二.STM32CubeMX安装过程 三.HAL库安装 四.HAL库实现LED流水灯 (一)新建项目 ...

  3. 【嵌入式04】用寄存器HAL库完成LED流水灯程序

    目录 一.原理学习 1.寄存器映射原理 2.GPIO端口的初始化设置步骤 二.LED流水灯 1.程序设计思路 2.寄存器方式编程实现 3.HAL库编程实现 4.软件仿真 三.总结 四.参考链接 一.原 ...

  4. ​用寄存器HAL库完成LED流水灯程序

    STM32的地址映射.寄存器映射原理以及GPIO端口的初始化设置三步骤 ​(一)STM32F103系列芯片的地址映射及寄存器映射原理 1.STM32F103C8T6简要介绍 ● STM32F103C8 ...

  5. 【嵌入式基础】用C语言编程、寄存器实现LED流水灯程序;stm32CubeMX+Keil使用HAL库点亮流水灯

    本文主要介绍STM32F103系列芯片的地址映射和寄存器映射原理,GPIO端口的初始化设置步骤.利用C语言编程和寄存器点亮流水灯以及stm32CubeMX+Keil使用HAL库点灯 目录 一.STM3 ...

  6. STM32F03寄存器方式点亮LED流水灯

    STM32F03寄存器方式点亮LED流水灯 文章目录 STM32F03寄存器方式点亮LED流水灯 一.题目内容 二.STM32F03系列芯片的地址映射和寄存器映射映射原理:了解GPIO端口的初始化设置 ...

  7. STM32F103寄存器方式点亮LED流水灯

    实验要求:以 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED 搭建电路,使用GPIOB.GPIOC.GPIOD这3个端口控制LED灯,轮流闪烁,间隔时长1秒.1)写出 ...

  8. pic单片机流水灯循环右移c语言,PIC单片机LED流水灯程序

    PIC 单片机 LED流水灯程序 ;************************************************************* include ;*********** ...

  9. led流水灯c语言数组程序,LED流水灯程序 一维数组写法

    LED流水灯程序 一维数组写法 /*********** (C) COPYRIGHT 201 2************ * 程序作者: 蓝雨(QQ:983931459 ,Email:chenheng ...

最新文章

  1. R语言ggplot2条形图(bar plot)可视化:更改一个条形(bar)的颜色、突出一个条形(bar)的颜色
  2. [LUOGU] P3128 [USACO15DEC]最大流Max Flow
  3. 计算机科学与技术真的会掉头发吗,大学“最辛苦”的三个专业,“脱发率”很高,毕业后却都很吃香!...
  4. java 自定义一个容器类
  5. 安卓7.0拍照遇到 Uri暴露错误
  6. C++实现通过UDP传输文件
  7. ASP.NET Core MVC 源码学习:MVC 启动流程详解
  8. 速达服务器账套定期维护么,速达软件常见操作问题解决方法
  9. 视频流传输协议RTP/RTCP/RTSP/HTTP的区别
  10. 阿里云明确生态边界:不做SaaS、被集成
  11. 最新版python如何安装qt5_Python3 搭建Qt5 环境的方法示例
  12. 计算机三角函数习惯原创的音乐,三角函数 UNIT版
  13. [导入]用事件和异常返回多种结果
  14. NVIDIA Nsight Systems 入门及使用
  15. OPNsense - 多功能高可靠易使用的防火墙(五)
  16. 【附源码】计算机毕业设计SSM网上商城比价系统
  17. 2021河南省高考成绩位次查询,2021年河南高考排名位次查询系统,河南高考排名查询入口...
  18. JSON.parse 转换字符串样式的数组
  19. 「短视频+社交电商」营销模式爆发式发展,带来的好处有什么?
  20. 【转】推荐系统原理、工程、大厂(Youtube、BAT、TMB)架构干货分享

热门文章

  1. 2023武汉集训总结
  2. 网络监控器mrtg全攻略
  3. 数字孪生是什么?【深度解析】
  4. 禁用和启用google翻译
  5. Parameter 'arg0' not found. Available parameters are [xxx, xxx, param1, param2]
  6. LLVM中指令的一生
  7. 使用element分页器进行新闻列表分页
  8. Keil 4 安装教程及简单使用【嵌入式系统】
  9. 欧姆龙程序PLC案例标准程序 使用欧姆龙CP1H写的脉冲伺服 步进控制程序案例
  10. VMware+Ubuntu16.04部署k8s多节点网络(二)——配置各节点网络