STM32和C51程序的设计与仿真(点亮LED灯)

一、STM32使用寄存器点亮LED灯

  1. 新建一个工程文件,并将启动文件 startup_stm32f10x_hd.s 引入到 Source Group 中。

    引入的启动文件根据自己的 stm32 定,此处引入的启动文件支持的是 stm32F1系列;

    文件所在位置:Libraries —> CMSIS —> CM3 —> DeviceSupport —> ST —> STM32F10x —> startup —> arm;

  2. 新建 main.c, 写入一下内容:

       int main(void)
       {
       	//打开GPIOB的时钟
       	*(unsigned int *)0x40021018 |= (1 << 3);
       	//配置IO口为输出
       	*(unsigned int *)0x40010C00 |= (1 << (4*0));
       	// 控制 ODR 寄存器
       	*(unsigned int *)0x40010C0C &= ~(1 << 0);	//(unsigned int *)将0x40010C0C强制转换为地址,前面再加指针进行指针的赋值操作
       }
       
       void SystemInit(void)
       {
       	//函数外定义SystemInt(), 骗过编译器不报错
       }
       
    
  3. 程序的说明

  • 定义一个 SystemInit 空函数的目的是为了骗过编译器;因为在启动文件中引入了 SystemInit 函数 (如图一),而我们此处在此处没有引入 stm32f10x.h 的固件库,所以应在 main 文件中定义一个空函数,不然将会报如下错误 (如图二)

    图一
    图二
  • 配置端口输出数据寄存器(GPIOx_ODR)

    由上图可知,要想 LED 灯PB0 亮,即将 PB0 对应的 GPIOB_ODR 置0,也就是将GPIOB_ODR0置0。

    由上图可知,GPIOB_ODR地址 = 0x40010C00(GPIOB初始地址) + 0x0C(偏移地址) = 0x40010C0C

    由上图知,将 GPIOB_ODR第0位置0,所以代码为:

         *(unsigned int *)0x40010C0C &= ~(1 << 0);// 控制 ODR 寄存器
    
  • 配置 PB0 的 IO 口为输出 (配置低寄存器GPIOB_CRL)

    因为 stm32 的 IO 口可以输出或者输入,默认情况下为输入,如上图所示。

    由上图可知,GPIOB_CRL地址 = 0x40010C00(GPIOB初始地址) + 0x00(偏移地址) = 0x40010C00

    由上图,选择配置 GPIOB_CRL第四位为0001,所以代码如下:

       *(unsigned int *)0x40010C00 |= (1 << (4*0));//配置IO口为输出
    
  • 位情况下,时钟处于关闭状态,需要打开 GPIOB 的时钟,否则将不会工作;

    由上图可知道,应打开 APB2 外设时钟使能寄存器(RCC_APB2ENR)

    由上图可知,RCC_APB2ENR地址 = 0x40021000(RCC初始地址) + 0x18(偏移地址) = 0x40021018

    由上图可知,要打开 GPIOB 的时钟,需将 RCC_APB2ENR 的第三位置1,所以代码应如下:

       *(unsigned int *)0x40021018 |= (1 << 3);	//打开GPIOB的时钟
    

二、STM32使用固件库点亮LED灯

  1. 新建一个工程文件,配置并引入固件库,具体操作这里将不会细诉 (此处引入的固件库版本为STM32F10x_StdPeriph_Lib_V3.5.0)

    如何新建一个工程模板,可参考此篇博文:MDK5 Kil5中STM32工程的建立过程

  2. 由寄存器点亮 LED 灯可知,点亮 LED 灯大致应有如下步骤:

    • 开启 GPIO 的端口时钟
    • 选择要具体控制的 IO 口,即 pin
    • 选择 IO 口输出的速率,即 speed
    • 选择 IO 口输出的模式,即 mode
    • 输出高/低电平
  3. 新建 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();
       }
       
    

    C语言的标准中变量必须在函数或者块的开始部分进行 声明/定义,而不像C++中是可以在任意位置定义变量,否则将会出现如下错误。

  4. 程序的说明

  • RCC_APB2PeriphClockCmd(RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) 控制 APB2 时钟函数 :

  • GPIO_InitTypeDef 将端口配置的 pin, speed,mode封装成结构体,同样 speed,mode被分别封装成枚举(enum) GPIOSpeed_TypeDef,GPIOMode_TypeDef

    typedef 的作用是给已知的数据类型命名别名

  • GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) 把配置好的端口参数写到 CRL 或者 CRH 这两个寄存器中。

  • GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 设置指定的数据端口(置0)。

  • GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 清除指定的数据端口(置1)。

三、Proteus进行仿真

  1. 在 keil5 工程目录下进行配置,点击魔法棒—>Output —> Create HEX File;

  2. 打开 Proteus,新建一个工程文件,并引入如下器件:

  3. 仿真点亮 PB0 端口上的 led 灯,电路图连接如下:

    注意:此处将 R1 的电阻值修改为了330,否则将会因为原电阻值太导致 led 不亮。

  4. 配置电网

    设计 —> 配置供电网 —> 将未连接电网增加到网络连接到GND

  5. 双击 STM32F103R6 芯片,链接 MDK 生成的 .hex 文件:

  6. 点击运行仿真,结果如下:

四、C51程序的设计和仿真

  1. 新建一个C51工程,可参考🔗:如何在KEIL C51 软件上创建一个工程

    注意:MDK和 KEIL C51 是不同开发工具,MDK是专为微控制器开发的工具;KEIL C51是支持绝大部分8051内核的微控制器开发工具

  2. 点击魔法棒,勾选 Create HEX File

  3. 新建一个 main.c 文件,并写入如下内容:

    #include "reg51.h"
    void main(void)
    {
    	P0 = 0xFE; //点亮P0端口上的LED灯
    }
    
  4. 切换到 Proteus,新建一个工程并引入如下器件:

  5. 仿真点亮 P0 端口上的 LED 灯,电路图设计如下:

  6. 双击 AT89C51芯片,链接 Keil C51 生成的 .hex 文件:

  7. 点击运行仿真,效果如下:

五、参考🔗:

Proteus仿真STM32流水灯实验例程、详细步骤

野火STM32F103教学视频

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值