STM32/51单片机编程入门(电亮LED流水灯)

一、安装并熟悉Proteus电路仿真软件,完成一个C51程序设计和仿真

1.安装Proteus仿真软件

参考文章

2.熟悉Proteus并完成一个C51程序设计和仿真

  • 创建工程

    自定义工程名称和路径

创建原理图

创建PCB

选择AT89C51芯片进行仿真

项目创建成功

  • 新工程创建完成后可以看到有三个窗口,分别是原理图窗口、PCB窗口、源代码窗口

  • 绘制LED流水灯原理图

  • 编写仿真程序

#include <REGX52.H>
#include<intrins.h>
void Delay200ms()       //@12.000MHz
{
    unsigned char i, j, k;
​
    _nop_();
    i = 2;
    j = 134;
    k = 20;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}
​
void main()
{
    while(1)
    {
        P2=0xFE;//1111 1110
        Delay200ms();
        P2=0xFD;//1111  1101
        Delay200ms();
        P2=0xFB;//1111  1011
        Delay200ms()    ;
        P2=0xF7;//1111  0111
        Delay200ms()    ;
        P2=0xEF;//1110  1111
        Delay200ms()    ;
        P2=0xDF;//1101  1111
        Delay200ms()    ;
        P2=0xBF;//1011  1111
        Delay200ms()    ;
        P2=0x7F;//0111  1111
        Delay200ms();
    }
}
  • 仿真程序运行

    双击芯片打开编辑元件,选择编译好的.hex文件,点击软件左下角的开始按钮开始仿真

        

运行成功

二、stm32电亮LED流水灯

  • 寄存器

    寄存器是CPU中有限存贮容量的高速存贮部件,可用来暂存指令、数据和地址。 简单来讲,如果将我们的计算机比作一栋大楼,而寄存器就是这栋大楼中的每一间房子,寄存器地址便可以看做是房子的门牌号,只不过这个门牌号有点特殊,是由0 1比特流构成的。

  • GPIO

    GPIO 是通用输入输出端口的简称,也就是STM32 可控制的引脚, STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。所有的 GPIO 引脚都有基本的输入输出功能。

1..stm32使用寄存器GPIO方式电亮LED流水灯

  • 新建stm32工程并引入stm32的固件库

  • 模块化编程

    为了降低主程序的复杂度、提高代码的可维护性、便于其它开发人员阅读理解代码、便于功能模块代码的迁移故使用模块化编程,在主程序中引入头文件后,直接调用相关功能模块即可。

    电亮流水灯需要一个延迟函数Delay

    Delay.h代码如下:

#ifndef __DELAY_H
#define __DELAY_H
​
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);
​
#endif

Delay.c代码如下:

#include "stm32f10x.h"
​
/**
  * @brief  微秒级延时
  * @param  xus 延时时长,范围:0~233015
  * @retval 无
  */
void Delay_us(uint32_t xus)
{
    SysTick->LOAD = 72 * xus;               //设置定时器重装值
    SysTick->VAL = 0x00;                    //清空当前计数值
    SysTick->CTRL = 0x00000005;             //设置时钟源为HCLK,启动定时器
    while(!(SysTick->CTRL & 0x00010000));   //等待计数到0
    SysTick->CTRL = 0x00000004;             //关闭定时器
}
​
/**
  * @brief  毫秒级延时
  * @param  xms 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_ms(uint32_t xms)
{
    while(xms--)
    {
        Delay_us(1000);
    }
}
​
/**
  * @brief  秒级延时
  * @param  xs 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_s(uint32_t xs)
{
    while(xs--)
    {
        Delay_ms(1000);
    }
} 
编写main文件
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
​
int main(void)
{
    //打开GPIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    //初始化端口
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;//初始化16个端口
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_ResetBits(GPIOA,GPIO_Pin_0);
    
    while(1)
    {
        GPIO_Write(GPIOA,~0x0001);//0000 0000 0000 0001 第一个LED电亮,其它熄灭
        Delay_ms(600);
        GPIO_Write(GPIOA,~0x0002);//0000 0000 0000 0010 
        Delay_ms(600);
        GPIO_Write(GPIOA,~0x0004);//0000 0000 0000 010 
        Delay_ms(600);
        GPIO_Write(GPIOA,~0x0008);//0000 0000 0000 100 
        Delay_ms(600);
        GPIO_Write(GPIOA,~0x0010);//0000 0000 0001 0000 
        Delay_ms(600);
        GPIO_Write(GPIOA,~0x0020);//0000 0000 0010 0000 
        Delay_ms(600);
        GPIO_Write(GPIOA,~0x0040);//0000 0000 010 0000 
        Delay_ms(600);
        GPIO_Write(GPIOA,~0x0080);//0000 0000 100 0000 
        Delay_ms(600);
    }
}
  • 接线

  • 编译、下载

2.总结

用程序直接配置寄存器是最底层、最直接、效率最高的方式,但是由于STM32的结构复杂、寄存器数量多,基于寄存器的方式在面对复杂庞大的工程项目时会极大的降低开发效率。对寄存器编程需要花费较多的时间学习和查阅STM32数据手册,这个过程繁琐、易错,难以移植。库函数就是用宏定义、枚举标识符等代表的数值写入寄存器,替用户摆脱枯燥的机械过程。在一些代码要求高效率的情况下,对寄存器编程是非常必要的。同时,对寄存器的学习与操作,将非常有助于我们在出错时进行程序调试。

三、理论概念-常见嵌入式岗位面试题

1.通过以上实践,结合阅读ARM、STM32技术手册,深入思考STM32F103系列芯片的地址映射和寄存器映射原理,GPIO端口的初始化设置的一般步骤,嵌入式C程序代码对内存(RAM)中的各变量的修改操作,与对外部设备(寄存器--->对应相关管脚)的操作有哪些相同与差别?

相同之处:

  1. 嵌入式C程序可以通过读写内存地址来修改变量的值,类似地,它也可以通过读写寄存器地址来操作外部设备。

  2. 在内存中修改变量的值和操作外部设备都需要使用特定的指令或函数来实现。

  3. 对变量和外部设备的修改操作都需要遵循特定的通信协议或硬件接口规范。

差别之处:

  1. 内存是嵌入式系统中的一部分,嵌入式C程序可以直接访问内存中变量的值并进行修改。而外部设备通常通过寄存器来控制,需要通过特定的寄存器地址来访问和修改设备寄存器的值。

  2. 内存操作主要涉及读取和写入变量的值,而外部设备操作通常涉及控制和配置设备的功能,例如设置模式、发送指令、读取状态、设置中断、还原现场等。

  3. 在内存中修改变量的值通常是即时的,而对外部设备的操作可能会引起设备的状态变化,需要按照特定的时序进行操作,如等待设备响应、设备初始化等。

  4. 对内存中变量的修改不涉及外部环境的限制,而对外部设备的操作可能受限于具体的硬件资源、接口标准、电源供应等因素。

2.为什么51单片机的LED点灯编程要比STM32的简单?

  1. 复杂性:STM32是基于ARM Cortex-M处理器的32位微控制器,功能和性能比51单片机更强大。它具有更多的外设和功能模块,提供更多的编程选项和灵活性。因此,STM32编程需要更多的配置和参数设置。相比之下,51单片机是8位的经典单片机,相对而言更简单。

  2. 开发环境:STM32通常使用Keil或CubeMX等集成开发环境进行开发,这些开发工具提供了丰富的库函数和代码生成工具,可以简化程序的编写和配置。而51单片机的开发环境相对简单,常用的是汇编语言或C语言,编写程序时需要直接对寄存器操作,程序量相对较小。

  3. 硬件资源:STM32通常具有更多的GPIO引脚和外设接口,这意味着需要更多的配置和初始化工作。而51单片机通常具有有限的GPIO引脚和外设接口,使得操控LED等简单外设相对容易。

3.与PC平台上的一般程序不同,嵌入式C程序经常会看见 register和volatile 关键字,请解释这两个变量修饰符的作用,并用C代码示例进行说明

  1. register关键字:

    • register关键字用于提示编译器将变量存储在寄存器中,以提高程序的执行效率。

    • 使用register关键字并不能保证变量一定会存储在寄存器中,它只是一个给编译器的提示,具体是否采用寄存器存储取决于编译器的实现以及目标平台的寄存器数量和可用性。

    • 一般来说,register关键字适用于频繁使用且对访问速度要求较高的变量,例如循环计数器等。并不是所有的变量都适合使用register关键字,过多地使用register可能导致编译器优化的效果不如预期。

下面是一个使用register关键字的示例:

register unsigned int counter; // 使用register关键字声明一个无符号整型寄存器变量
​
int main() {
    for (counter = 0; counter < 100; counter++) {
        // 在循环中使用寄存器变量
    }
    return 0;
}
  1. volatile关键字:

    • volatile关键字用于提示编译器,该变量可能会被程序以外的因素修改,因此每次访问时都应该从内存中重新读取变量的值,而不是使用之前缓存的值。

    • 常见的可导致变量值发生变化的因素包括硬件中断、多线程环境下的共享变量等。

    • 使用volatile关键字可以确保访问变量时的可见性和正确性,防止编译器进行不必要的优化。

    • 需要注意的是,volatile关键字并不能保证变量的原子性和同步性,仅仅保证了变量在每次访问时都重新从内存中读取。

下面是一个使用volatile关键字的示例:

volatile int flag; // 使用volatile关键字声明一个整型变量
​
int main() {
    while (flag != 1) {
        // 检查flag变量是否被修改
    }
    // flag为1时跳出循环
    return 0;
}
 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
流水灯是一种基本的电子电路,常用于电子制作、嵌入式开发等领域中。在流水灯的程序中,通常会使用循环语句和延时函数来实现灯的闪烁效果。下面是流水灯程序的调试过程和分析: 1. 编写代码:编写流水灯的代码,包括引脚的定义、初始化和循环语句等。 2. 上传代码:将代码上传到开发板或者仿真环境中,进行编译和烧录。 3. 调试程序:运行程序,观察流水灯的闪烁效果是否符合预期。 4. 分析问题:如果程序出现问题,需要分析问题的原因。常见的问题包括流水灯无法闪烁、闪烁速度过快或过慢、灯的顺序错误等。 5. 解决问题:根据问题的原因,进行相应的调整和修改。常见的解决方法包括修改循环语句、调整延时时间、更换引脚等。 6. 重新测试:修改完成后,重新测试程序,确保流水灯的闪烁效果符合预期。 在调试流水灯程序时,需要注意以下几点: 1. 引脚定义:在程序中定义引脚时,需要确保引脚的编号和实际连接的引脚一致。 2. 循环语句:循环语句的次数和延时时间可以影响流水灯的闪烁效果,需要进行适当的调整。 3. 延时函数:延时函数的精度和稳定性会影响流水灯的闪烁效果,需要选择合适的延时函数或者根据实际情况自行编写延时函数。 4. 硬件问题:流水灯的闪烁效果还受到硬件因素的影响,如电源电压、电阻大小等,需要进行相应的检测和调整。 总之,调试流水灯程序需要耐心和细心,需要不断尝试和调整,才能得到符合预期的闪烁效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值