stm32入门-流水灯-C51和stm32的对比

目录

前言 

一、基于c51芯片的流水灯

1.借助Proteus软件绘制电路图

2.编写代码,生成.hex文件 

引入头文件 

创建LED数组 

建立延时函数

编写主函数

运行文件,生成.hex文件

3.烧录.hex文件,实现仿真 

二、基于stm32芯片的流水灯

三、总结


前言 

本文是适合单片机新手的,因此借助c51使用寄存器形式驱动芯片的方式下,stm32同样采用寄存器方式,最终形成对比,从而能够有更深刻的体验 

一、基于c51芯片的流水灯

1.借助Proteus软件绘制电路图

本文采用低电平有效的方式,因此在lLED灯的另外一边接入的是电源,也就是,当I/O口为低电平的时候,电路接通,LED灯亮,另外c51的I/O口很多,例如P0、P1等,因此选用一个即可,最终绘制出的电路图如下所示:

2.编写代码,生成.hex文件 

引入头文件 

由于c51和c52功能性质相似,c52只是增强了部分功能,因此本文直接是在c52的环境下编写的

#include <regx52.h>

创建LED数组 

根据低电平有效,因此将需要亮的LED灯赋值为0,其余均为1,创建数组如下:

//创建流水灯数组
unsigned char led[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

建立延时函数

因为单片机在运行的时候速度很快,因次插入延时函数可以让程序按照我们所设定的时间进行运行, 本文由于对于流水灯闪烁的间隔没有要求,因此时间可以随意设定,想要具体准确的使劲按,可以使用软件生成一个准确时间的延时函数代码,本文代码如下:

void delay()
{
	int i,j;
	for(i=0;i<1000;i++)
	for(j=0;j<30;j++);//其中的i和j可以根据直接需求设定
}

编写主函数

 本文引入一个变量k,方便实现八个流水灯持续交替闪烁,也就是当第八个灯亮完之后,恢复程序,继续使第一个灯继续亮,在每一个灯亮完之后加一个延时,更加方便观察,减缓闪烁频次

//主函数
void main()
{
	int k=0;
	while(1)
	{
		P1=led[k];
		delay();
		k++;
		if(k==8)
			k=0;//建立循环,当最后一个灯亮后,使第一个灯继续亮
	}
}

最后所有代码整合起来,如下:

#include <regx52.h>

//创建流水灯数组
unsigned char led[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

//延时
void delay()
{
	int i,j;
	for(i=0;i<1000;i++)
	for(j=0;j<30;j++);
}

//主函数
void main()
{
	int k=0;
	while(1)
	{
		P1=led[k];
		delay();
		k++;
		if(k==8)
			k=0;//建立循环,当最后一个灯亮后,使第一个灯继续亮
	}
}

运行文件,生成.hex文件

点击魔法棒在output一栏下,按如下选择

点击运行,随后将生成一个.hex文件 

3.烧录.hex文件,实现仿真 

双击仿真软 件中的芯片,浏览栏中选中上诉生产的.hex的文件,开始仿真,运行结果如下:

 

 

4.程序优化

上文将LED灯以数组的形式进行点灯,但是通常情况下,是使用移位的方式,代码如下: 

#include <regx52.h>

//延时
void delay()
{
	int i,j;
	for(i=0;i<1000;i++)
	for(j=0;j<30;j++);
}

void main()
{
	int i;
	while(1)
	{
	    for (i=0;i<8;i++)
	        {
		    P1=~(0x01<<i);
//每次向左移i位,空出来的补0;由于本文是低电平有效,所以最终取反
		    delay();
	        }
	    if(i==8)i=0;
    }
}

 以上运行效果与之前相同。

二、基于stm32芯片的流水灯

本文的寄存器方式主要是为了能够和C51芯片进行对比。

(1)绘制电路图

本文使用GPIOA的PA0引脚对LED灯进行控制

(2)编写代码

本文选用的是APB2外设使能寄存器(RCC_APB2ENR),同时输出时选用的是PA0引脚

#include "stm32f10x.h"                  // Device header
int main(void)
{
    while(1)
    { 
        //配置时钟RCC 0100
        *(unsigned int *)0x40021018|=(1<<2);
        //配置位寄存器CRL 0001
         // 配置PA0为推挽输出模式
    *((unsigned int *)0x40010800) &= ~(0x3 << 0); // 清除PA0的模式和配置位
    *((unsigned int *)0x40010800) |= (0x2 << 0); // 设置PA0为推挽输出模式
        //配置数据寄存器ODR
        (*(unsigned int *)0x4001080C) &=~(1);//寄存器
        //40010800[GPIOA的首位地址]+0Ch[ODR的地址偏移]=GPIOA_ODR0[PA0的地址]
        //1的二进制为0000 0001
        
    }
  }
配置时钟

RCC的偏移地址:0x18

RCC的初始地址:0x40021000

RCC_APB2ENR地址:0x40021018

配置数据寄存器

GPIOA初始地址:0x40010800

偏移地址:0x0Ch

GPIOA_ODR0地址:0x4001080C

配置位寄存器

GPIOA初始地址:0x40010800

偏移地址:0x00

GPIOA_CRL0地址:0x40010800

(3)程序仿真结果

经过Proteus仿真结果如图所示

(2)实物烧录结果

三、问题的思考

嵌入式C程序代码对内存(RAM)中的各变量的修改操作,与对外部设备(寄存器--->对应相关管脚)的操作有哪些相同与差别?

嵌入式C程序代码对内存中的变量的修改操作与对外部设备(寄存器)的操作有一些相同和一些差异。相同之处在于它们都涉及到对内存和寄存器的读写操作。无论是修改内存中的变量还是配置外部设备的寄存器,都需要通过读取和写入操作来实现。
然而,它们的差异在于目标和访问方式。对内存中的变量进行修改主要是为了在程序中存储和处理数据。在嵌入式系统中,使用RAM(随机存取存储器)来存储变量数据是常见的做法。通过C语言中的变量赋值语句,可以直接将新值写入变量所在的内存地址。
对外部设备的操作通常涉及对寄存器的访问。外部设备(例如芯片、传感器或接口芯片)通常会包含一组寄存器,用于配置设备的功能和状态。通过向寄存器写入特定的值,可以控制设备的行为。在嵌入式C程序中,通过给寄存器赋值,可以实现对外部设备的操作。

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

51单片机和STM32是两种常见的嵌入式系统开发平台。在51单片机上进行LED点灯编程相对比较简单的原因有以下几点:
51单片机的架构相对较简单,指令集和寄存器设计也较为简洁。因此,编写代码并操作寄存器来控制LED的点灯相对容易理解和实现。
在51单片机上,通常使用汇编语言来编写嵌入式代码,与C语言相比,汇编语言更直接地操作寄存器和设备。这使得对51单片机进行底层设备编程更加简单。
在开发过程中,51单片机的资源(例如GPIO引脚)通常较为有限,这使得其编程相对简单。对于简单的操作,可以直接使用特定的寄存器位来控制LED点亮或熄灭。
相比之下,STM32是一种更强大且复杂的嵌入式系统开发平台,具有更多的功能和资源。STM32系列芯片通常配备了更多的外设和功能模块,这要求程序员在编程时需要更深入地理解与配置这些功能。此外,STM32开发通常使用C语言编写,这为开发者提供了更高级的抽象和方便的开发环境,但同时也存在更多的库函数和API需要学习和使用。综合而言,STM32上的开发相对复杂,但也能提供更多更灵活的功能和扩展性。

register和volatile 关键字

在嵌入式C程序中,经常会使用`register`和`volatile`这两个变量修饰符来对变量进行特殊的声明和使用。
1)`register`关键字:
`register`关键字用于向编译器建议将变量存储在寄存器中,以提高访问速度和效率。但是,`register`关键字只是对编译器的建议,并不能强制将变量存储在寄存器中,因为寄存器的数量和可用性是由编译器决定的。

示例代码:

register int x; // 声明一个建议存储在寄存器中的变量x


需要注意的是,`register`关键字不能用于全局变量或函数参数,因为全局变量和函数参数已经有它们自己的存储约定。
2)`volatile`关键字:
`volatile`关键字用于告诉编译器该变量可以被意外地修改,这样编译器就不会进行某些优化,以确保对该变量的访问具有可见性。在嵌入式系统中,`volatile`通常用于访问外部设备的寄存器,或在多线程/中断环境中访问共享数据。

示例代码:

volatile int flag; // 声明一个可变的标志变量flag


在使用`volatile`关键字修饰的变量时,编译器不会进行某些优化,例如对变量的缓存读取和编译器重排等。这是因为`volatile`变量的值可能会在未经程序代码直接操作的情况下发生变化,例如由硬件中断修改。

总结来说,`register`关键字建议把变量存储在寄存器中以提高访问效率,而`volatile`关键字用于声明可变的变量,并告诉编译器不要做某些优化,以确保访问的可见性。在嵌入式C程序中,使用这些关键字可以更好地管理和访问硬件资源。

四、总结

在寄存器方式下,c51会比stm32简单,因为c51的端口、功能没有stm32复杂,因此是stm32通常采用库函数或者HAL的形式。 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
stm32--tsl256.zip_stm32是一个压缩文件,其中包含了与stm32和tsl256芯片相关的文件和代码。stm32是一种32位的单片机系列,由STMicroelectronics公司推出。它具有高性能、低功耗和丰富的外设接口,适用于各种嵌入式系统应用。tsl256是一种环境光传感器芯片,用于检测周围环境的光照强度。 这个压缩文件可以包含stm32芯片和tsl256传感器之间的通信协议、引脚连接方式、初始化代码以及一些示例应用程序。通过使用这些文件和代码,开发人员可以很方便地在stm32上使用tsl256传感器来测量光照强度。例如,可以通过读取tsl256传感器输出的模拟电压值,转换为相应的光照强度数值。开发人员可以根据需要进行修改和定制,以适应具体的应用场景。 使用stm32--tsl256.zip_stm32文件,开发人员可以节省大量的开发时间和精力。他们无需从零开始编写通信协议和初始化代码,也无需从头研究如何与tsl256传感器进行交互。相反,他们可以直接使用这些提供的文件和代码,快速实现与tsl256传感器的集成,并进行光照强度的测量和应用开发。 总之,stm32--tsl256.zip_stm32是一个方便开发人员在stm32上使用tsl256传感器的压缩文件。它包含了相关的文件和代码,可以用于通信协议、引脚连接、初始化以及示例应用程序。通过使用这些文件和代码,开发人员可以快速、方便地实现在stm32上使用tsl256传感器进行光照强度测量和应用开发

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值