STM32/51单片机开发编程入门(以点亮一个LED为例子)

STM32/51单片机编程入门(点亮LED)

前言

单片机是微控制器的核心部件,它可以控制外围电路完成各种功能。单片机编程是学习单片机应用的基础。本实验将结合主流的嵌入式开发软件(Proteus和Keil),以及结合STM32单片机来完成一个简单的点亮LED的任务,从而入门STM32单片机的编程。

STM32是目前应用最广泛的32位微控制器之一。它采用ARM内核,性能强大,资源丰富。本实验选择STM32F103C8T6作为开发板,它内置一个RGB彩色LED。通过编写程序控制单片机的I/O口输出高电平,就可以点亮这个LED。

本实验的目的是让学习者了解STM32单片机的基本结构和工作原理,掌握如何编写简单的C语言程序控制单片机I/O口输出,从而入门STM32单片机编程。通过完成这个简单的点亮LED任务,学习者可以初步掌握单片机编程的流程,为后续学习奠定基础。这对于进一步学习单片机应用和其他更复杂的项目将很有帮助。

Proteus的入门

Proteus的简介和安装

Proteus的简介

Proteus是一款功能强大的电路仿真软件,广泛应用于单片机和嵌入式系统的研发设计与调试。
Proteus具有以下主要特点:

  • 硬件资源丰富,内置大量单片机和外设模型,支持众多主流单片机芯片如8051、AVR、PIC、ARM等,以及大量外设模块。
  • 软件资源完善,内置C/C++编译器和调试器,支持Keil、IAR等IDE项目直接加载仿真。
  • 真实性强,支持电路级和逻辑级仿真,模拟实物电路运行状态。各种外设模型行为接近真实芯片。
  • 交互性好,界面直观,支持波形、逻辑分析等功能,可实时监测变量变化。
  • 兼容性强,支持主流操作系统,软件更新频繁兼容新版本单片机。
  • 价格实惠,学生版免费,商业版价格适中,对个人和小团队都友好。

Proteus使用过程主要包括:选择单片机和外设模型、绘制电路图、导入程序代码、设置仿真参数、运行和调试。它可以帮助设计人员在PC端完成电路和程序的联合调试,大幅提高开发效率。
通过Proteus,设计人员可以在不烧录芯片的情况下,对程序功能进行验证,找到和修复bug。在产品上市前也可以进行模拟测试,减少后续问题。它为单片机和嵌入式系统的研发提供了强大的辅助工具支持。

Proteus的安装

首先,下载Proteus的安装包,链接如下:
链接: https://pan.baidu.com/s/1SICOxDbywiL5S4RN1vvkKA
提取码:7wb7
安装步骤
1.选择我们下载的安装包,右键解压:
在这里插入图片描述

2.解压后,右键以管理员身份运行安装程序:
在这里插入图片描述

3.点击next:
在这里插入图片描述
此处不推荐修改安装路径,因为可能识别不到(如中文路径问题等等)

4.完成安装:
在这里插入图片描述

5.汉化:
打开解压后的安装包,进入汉化补丁文件夹,复制Translations文件夹到软件安装目录(参考第3步安装路径)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
即可汉化成功。

6.进入软件:
在这里插入图片描述

完成一个C51程序设计和仿真

创建新工程:
在这里插入图片描述
在这里插入图片描述
一直点下一步,创建完成后,在目录里面可以看见工程文件:
在这里插入图片描述
Proteus的具体用法可以参考下面的博客:
链接: https://blog.csdn.net/weixin_43772810/article/details/121993865?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169535133016800182720775%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=169535133016800182720775&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-121993865-null-null.142v94insert_down28v1&utm_term=proteus&spm=1018.2226.3001.4187

不选择模板,创建空工程,从零开始学起
在这里插入图片描述
选择元件,点击P,插入元件
如果出现Proteus提示No Libraries Found!
这个错误是可能由于软件下载在C盘,软件需要使用外部库时会申请管理员身份
请以管理员身份运行Proteus
在这里插入图片描述
选择AT98C51单片机:
在这里插入图片描述

选择电阻:
在这里插入图片描述
选择LED:
在这里插入图片描述
连接元器件并添加网格编号:
在这里插入图片描述
在Keil中编写程序(Keil简介见下一节)

#include <REGX52.H>
#include <INTRINS.H>

void Delay500ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void main()
{
	while(1)
	{
		P2=0xFE;//1111 1110
		Delay500ms();
		P2=0xFD;//1111 1101
		Delay500ms();
		P2=0xFB;//1111 1011
		Delay500ms();
		P2=0xF7;//1111 0111
		Delay500ms();
		P2=0xEF;//1110 1111
		Delay500ms();
		P2=0xDF;//1101 1111
		Delay500ms();
		P2=0xBF;//1011 1111
		Delay500ms();
		P2=0x7F;//0111 1111
		Delay500ms();
	}
}

编译并选择生成hex文件:
在这里插入图片描述
在这里插入图片描述
双击Proteus中的单片机,将生成hex放在Program File中:
在这里插入图片描述
之后点点击左下角的开始仿真,得到的仿真结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以下省略,请读者自行仿真

Keil的入门

Keil的简介和安装

Keil简介

Keil软件是一款广泛应用于单片机开发的集成开发环境,由英国Keil公司研发。
Keil软件主要特点:

  • 支持众多主流单片机架构,如8051、AVR、ARM、LPC等,适用于不同领域的嵌入式开发。
  • 内置C/C++编译器,支持标准C语言编程,编译速度快源代码结构清晰。
  • 调试功能强大,支持单步调试、断点设置、变量监视等,有效定位bug。
  • 项目管理便利,支持不同配置的项目切换,方便团队协作开发。
  • 下载功能灵活,支持串口、JTAG等方式下载程序到单片机。
  • 资源管理完善,内置单片机资料库和例程,快速上手常用单片机。
  • IDE界面简洁明了,支持主流操作系统,学习成本低。
    Keil软件开发流程主要包括:添加头文件、编写C源代码、设置编译选项、生成二进制文件、下载调试等步骤。它为用户提供了从代码编写到烧录调试的一站式解决方案。
    Keil软件广泛应用于各行各业的单片机开发。它编译速度快,调试方便,对初学者友好,是入门和学习单片机编程的首选IDE。同时也被工业界认可为高效可靠的嵌入式开发平台。

Keil安装

Keil的安装请参考以下链接:
链接: https://mp.weixin.qq.com/s/1UVYHxQShMx9SWxEirq3zA

使用Keil编写一个简单的程序

硬件的搭建

硬件的简介

硬件采用STM32F103系列的单片机,STM32F103系列是STMicroelectronics推出的一系列低成本ARM Cortex-M3内核32位微控制器。它采用ARM32位Thumb指令集,主频高达72MHz,内置128KB至512KB的FLASH及20KB至40KB的RAM。
在这里插入图片描述

STM32F103系列单片机适用于消费类电子、工业控制、医疗设备等各种嵌入式应用。它具有丰富的外设,如ADC、DAC、PWM、SPI、I2C、CAN总线等,性能稳定可靠。
本次实验具体采用的时STM32F103C8T6单片机,其主要参数如下:

部件参数
微控制器ARM32位Cortex-M3内核
主频72MHz最大主频
FLASH128KB
SRAM20KB
ADC12位ADC,最大1.2MSPS采样率
DAC12位DAC
USART3路USART
I2C1路I2C
SPI2路SPI
TIMER4路16位定时器
PWM4路PWM输出
RTC实时时钟
WWDG看门狗定时器
工作电压2.0-3.6V
封装型号LQFP48(7x7mm)
操作温度-40~85°C

STM32F103C8T6单片机集成丰富的外设,适用于各种消费类和工业控制产品的开发,性能稳定可靠。它是STM32F103系列的低成本代表型号。

烧录一个程序(点亮一个LED灯)

软件的编写

main.c文件

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	while (1)
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_0);
		Delay_ms(500);
		GPIO_SetBits(GPIOA, GPIO_Pin_0);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
		Delay_ms(500);
	}
}
/*
 这个代码是用STM32单片机控制GPIOA端口的PA0引脚来闪烁LED,实现了不同方式控制GPIO的比较:
1. GPIO_ResetBits和GPIO_SetBits函数:
- GPIO_ResetBits(GPIOA, GPIO_Pin_0)将PA0设置为低电平(复位状态)
- GPIO_SetBits(GPIOA, GPIO_Pin_0)将PA0设置为高电平(设置状态) 
2. GPIO_WriteBit函数与枚举类型:
- GPIO_WriteBit有两个参数,第一个是GPIO端口,第二个是枚举类型BitAction的取值:
  Bit_RESET(0)或Bit_SET(1)
3.直接使用0/1整数:
- GPIO_WriteBit第二个参数也可以直接传入0或1来实现相同功能
总体来说:
- 三种方式都可以控制GPIO输出高低电平来闪烁LED
- GPIO_ResetBits/GPIO_SetBits更加直观
- GPIO_WriteBit与枚举类型定义更加规范
- 直接0/1更简洁,但不如上面两种明确
所以这段代码通过控制GPIO的不同写法,实现了LED的闪烁,同时对比了STM32驱动库中GPIO控制的三种主要方式。
*/

延时函数:

#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);
	}
} 

硬件的连接

烧录器的连接方式:
在这里插入图片描述
LED灯的连接方式:
在这里插入图片描述
实物连接:
在这里插入图片描述
ST-LINK的连接一定要正确,否则会烧录失败

实验效果

首先,在Keil中对工程文件进行编译,点击Rebuild:
在这里插入图片描述
等待,得到的编译结果:
在这里插入图片描述
可以看见,工程通过了Keil的编译,没有错误和警告。
紧接着,点击DownLoad,将程序烧录进单片机:
在这里插入图片描述
如果出现了以下问题:
在这里插入图片描述
可以参考下面的博客:
链接: https://blog.csdn.net/Chrstian/article/details/123432805

得到的结果:
在这里插入图片描述

思考问题

问题一

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

解答:
嵌入式C程序代码对内存(RAM)中的变量和对外部设备(寄存器->对应管脚)的操作在以下几点有差别:
相同点:

  1. 都通过变量或寄存器来实现对内存或外设的读写操作。
  2. 变量和寄存器都通过定义来代表内存或外设中的一个地址空间。

差异点:

  1. 变量操作对象是内存中的RAM空间,寄存器操作对象是外设内部的寄存器空间。
  2. 变量操作直接影响内存中的数据,寄存器操作通过改变寄存器的值来控制外设的工作状态或数据线的电平变化。
  3. 变量地址是相对地址,寄存器地址通常是绝对物理地址,对应单片机总线上的确定端口。
  4. 变量类型限定了可读写的数据格式,寄存器根据数据手册说明对应不同功能。
  5. 变量在内存中以字或字节为单位读写,寄存器根据不同外设可能以单个bit为单位操作。
  6. 变量生命周期在程序运行期间,寄存器对应外设的工作状态在单片机上电期间。

所以总体来说,变量操作对象是内存,寄存器操作对象是外设,二者在操作目的和方法上有明显差异。

问题二

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

解答:
51单片机LED点灯编程比STM32简单主要有以下几点原因:

  1. 51单片机I/O口直接连接LED,只需将口线设置为输出状态并输出高电平就可以点亮LED。而STM32需要通过外设驱动LED,增加了一层复杂度。
  2. 51单片机I/O操作直接使用单指令搞定,如SETB、CLR等。STM32需要配置外设寄存器,增加了编程难度。
  3. 51单片机没有内部外设,I/O口操作不需要外设时钟和初始化设置。STM32外设操作前需要配置时钟树、复用功能等。
  4. 51单片机资源较少,I/O口地址简单,不需要考虑资源冲突问题。STM32资源丰富,需要选择合适的I/O口和外设通道。
  5. 51单片机指令简单直观,不需要了解复杂的ARM指令集。STM32需要掌握ARM指令和寻址模式。
  6. 51单片机开发环境简单,如ISIS、Proteus等模拟器支持好。STM32需要使用IDE环境如MDK、IAR等,开发门槛较高。
  7. 51单片机例程少,例如LED点亮只需几行代码。STM32例程复杂,需要考虑更多细节问题。

所以总体来说,51单片机资源简单,I/O操作直观,开发门槛低,所以LED点亮编程难度小于STM32。STM32强大但复杂度也更高。

问题三

(理论概念-常见嵌入式岗位面试题) 与PC平台上的一般程序不同,嵌入式C程序经常会看见 register和volatile 关键字,请解释这两个变量修饰符的作用,并用C代码示例进行说明。

解答:
register和volatile这两个变量修饰符在嵌入式C程序中使用频率很高,主要作用是:
register关键字:

  • 用于声明自动变量,目的是告诉编译器这个变量最好分配在寄存器中存储,而不是内存,以提高访问速度。

例如:

register int i;
volatile 关键字: 
  • 用于声明那些可能由外部因素改变值的变量,禁止编译器对这些变量进行优化。
  • 比如外设寄存器、静态变量等,它们的值可能由硬件或中断更改。
  • 例如:
volatile unsigned int LED=0; 
void main()
{
  LED=1; //点亮LED
  while(1);
}
void interrupt() //中断服务程序
{
  LED=0; //关闭LED
}

在这个例子中:

  1. 使用register声明i变量,告诉编译器优先分配寄存器存储。
  2. 使用volatile声明LED变量,告诉编译器不要对这个变量进行优化,以保证主程序和中断程序看到的LED值一致。

所以总结来说,register用于性能优化,volatile用于解决多任务访问变量值不一致的问题。

总结

本实验通过编程控制单片机点亮LED,实现了单片机编程的基本流程,包括硬件连接、软件开发和调试三个部分。
硬件方面,将单片机开发板与LED连接好后,通过Proteus进行模拟测试,验证硬件设计是否正确。
软件方面,使用Keil软件开发环境编写C语言程序,控制单片机I/O口输出高电平点亮LED。程序包括初始化外设时钟、配置I/O口、实现主循环输出等内容。
调试方面,将程序下载到单片机后,可以直接在开发板上观察LED是否点亮。也可以将开发板连接到Proteus进行整体模拟,查看LED在仿真环境下是否正常工作。
通过这个简单的实验,学习者了解了单片机编程的基本流程,包括硬件连接设计、软件开发编程和调试测试三个步骤。此外也掌握了Proteus和Keil这两个常用的嵌入式开发工具的使用方法。
总体来说,这个LED点亮实验实现了单片机编程的入门,为学习者学习更复杂应用奠定了基础。同时也初步掌握了嵌入式开发的基本流程。这对后续深入学习单片机编程和项目开发很有帮助。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值