STM32点亮LED灯
文章目录
一.使用寄存器点亮LED灯
新建main.c
写入以下内容
int main(void)
{
//打开GPIOB的时钟
*(unsigned int *)0x40021018 |= (1 << 3);
//配置IO口为输出
*(unsigned int *)0x40010C00 |= (1 << (4*0));
// 控制 ODR 寄存器
*(unsigned int *)0x40010C0C &= ~(1 << 0);
}
void SystemInit(void)
{
//函数外定义SystemInt(), 骗过编译器不报错
}
将内容保存为.c文件并添加到Source group1中
二.使用固件点亮LED灯
新建main.c文件
写入以下内容
#include "stm32f10x.h"
//定义宏,提高程序的可移植性
#define LED_GPIO_PIN GPIO_Pin_0
#define LED_GPIO_PORT GPIOB
#define LED_GPIO_CLK RCC_APB2Periph_GPIOB
void LED_GPIO_Config(void)
{
//定义GPIO_InitTypeDef结构体
GPIO_InitTypeDef GPIO_InitStruct;
//开启时钟
RCC_APB2PeriphClockCmd(LED_GPIO_CLK, ENABLE);
//端口配置
GPIO_InitStruct.GPIO_Pin = LED_GPIO_PIN; //配置位(I/O口)
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //配置输出速度
//GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) 参数一:端口,参数二:GPIO_InitTypeDef结构体指针
GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct); //初始化GPIO
//点亮LED
GPIO_ResetBits(LED_GPIO_PORT, LED_GPIO_PIN);
//熄灭LED
//GPIO_SetBits(LED_G_GPIO_PORT, LED_G_GPIO_PIN);
}
int main(void)
{
// 程序来到 main 函数之前,启动文件:statup_stm32f10x_hd.s 已经调用
// SystemInit()函数把系统时钟初始化成 72MHZ
// SystemInit()在 system_stm32f10x.c 中定义
// 如果用户想修改系统时钟,可自行编写程序修改
LED_GPIO_Config();
}
三.使用Proteus进行仿真
1.在keil5工程目录下进行配置,点击魔法棒->output->Create HEX FILE。
2.打开Proteus新建工程文件,并引入LED RES 以及stm32f103R6
3.仿真点亮PB0端口上的LED灯,电路图如下
4.配置电网
设计->配置供电网->将未链接电网增加到网络连接到GND
5.双击stm32芯片,连接MDK生成的.hex文件
6.运行后成功。
问题思考
1)嵌入式c程序代码对内存(RAM)中的各变量的修改操作,与对外部设备的操作有哪些相同与差别
相同之处:
都需要采用相应的编程语言实现;
都需要使用相应的编程工具进行开发和测试;
都需要遵循相应的编程规范和标准,以确保编写出高质量、可靠、安全的代码;
都需要在程序中使用相应的数据类型、函数库等,以实现相应的功能。
差异之处:
对于内存中的变量修改操作,是直接读写内存地址的方式进行的,而对于外部设备的操作,则需要使用相应的硬件接口或协议来进行通信;
2)为什么51单片机的LED灯编程要比stm32的简单?
简单的编程风格,编程难度低,硬件资源相对简单,基础教学资料丰富。
3)与PC平台上的一般程序不同,嵌入式C程序经常会看见 register和volatile 关键字,请解释这两个变量修饰符的作用,并用C代码示例进行说明。
register关键字:
在嵌入式C程序中,register关键字用于提示编译器将变量存储在寄存器中,以便提高程序的执行效率。它用于修饰变量声明,并且不能修饰全局变量或指针类型的变量。
使用register关键字的主要目的是通过减少内存访问次数来提高代码的执行速度。由于寄存器的访问速度比内存要快得多,因此将经常使用的变量放置在寄存器中可以有效地减少对内存的访问。然而,由于寄存器的数量有限,编译器可能会忽略register关键字的请求。
示例代码:
void main() {
register int x = 10; // 使用register关键字修饰变量x
// 对变量x进行操作
x = x + 5;
// 将变量x的值输出
printf("x = %d", x);
}
volatile关键字:
在嵌入式C程序中,volatile关键字用于告诉编译器该变量可能会在程序执行期间发生变化,以防止编译器对这些变量进行优化。它常用于修饰与外部设备或并发任务相关的变量,以确保对其进行准确的读写操作。
使用volatile关键字后,编译器将不会对该变量的读写操作进行优化,以避免出现不可预料的结果。这是因为volatile关键字告知编译器,在每次引用该变量时都需要从内存中读取最新的值,而不使用缓存的数据。
示例代码:
volatile int sensorValue; // 使用volatile关键字修饰变量sensorValue
void main() {
// 从传感器中读取数值
sensorValue = readSensor();
// 检测传感器数值是否发生变化
while (1) {
if (sensorValue != readSensor()) {
// 传感器数值发生变化
printf("Sensor value changed!");
break;
}
}
}
在上述代码中,由于sensorValue变量被修饰为volatile,编译器会确保每次访问该变量时都从内存中读取最新值,以便及时检测传感器数值是否发生变化。