MDK 开发环境与 Proteus 仿真软件(8个led循环点亮)

1、新建项目

利用库文件构建
型号:STM32F103R6

  • 库函数下载

[https://pan.baidu.com/s/1l02hIqlM-L4AKW0pWZ2-hA?pwd=1c46]

  • 新建项目文件,如:Demo1_LedTest
  • 在该文件夹下分别新建Doc、FWLib、Driver、Project、Startup、User文件夹

file

allfile

  • 说明
文件名存放文件
Doc说明书,程序功能、版本、修改记录
FWLib库函数及核函数
Driver各个接口的初始化文件及头文件、启动代码
Project工程项目名称、输出
Startup启动配置文件
User主程序及应用程序
  • 新建一个工程到Project文件夹下

  • 在工程文件夹内几个文件夹:User、Project、Doc、Drivers、Libraries

keil

2、绘制仿真图

仿真图1

3、程序流程图
  • 主程序流程图

实验1流程图

  • 子程序流程图

在这里插入图片描述

4、编写主程序和程序

主程序main.c

#include "stm32f10x.h"
#include "bsp_led.h"
#include "delay.h"
int main(void)
{
    /*定义变量*/
    /*初始化硬件接口*/
    led_init_all(); //初始化与 LED 连接的硬件接口
    while(1)
    {
        
        led_on(LED0);
        delay_ms(20);
        led_off(LED0);
        delay_ms(20);
        led_on(LED1);
        delay_ms(20);
        led_off(LED1);
        delay_ms(20);
        led_on(LED2);
        delay_ms(20);
        led_off(LED2);
        delay_ms(20);
        led_on(LED3);
        delay_ms(20);
        led_off(LED3);
        delay_ms(20);
        
        led_on(LED4);
        delay_ms(20);
        led_off(LED4);
        delay_ms(20);
        led_on(LED5);
        delay_ms(20);
        led_off(LED5);
        delay_ms(20);
        led_on(LED6);
        delay_ms(20);
        led_off(LED6);
        delay_ms(20);
        led_on(LED7);
        delay_ms(20);
        led_off(LED7);
        delay_ms(20);
    } 
}


子程序bsp_led.h

#ifndef __BSP_LED_H
#define __BSP_LED_H

#include "stm32f10x.h"

/// LED硬件配置
#define LED_NUM                         8                                       ///< 设置LED的数量, 该驱动最多允许16个LED灯
#define LED_LEVEL                       0                                       ///< 0, 低电平点亮LED. 1, 高电平点亮LED

#define LED0_PORT     GPIOC               /* GPIO端口 */
#define LED0_CLK      RCC_APB2Periph_GPIOC  /* GPIO端口时钟 */
#define LED0_PIN  GPIO_Pin_0           /* 连接到SCL时钟线的GPIO */

#define LED1_PORT     GPIOC               /* GPIO端口 */
#define LED1_CLK      RCC_APB2Periph_GPIOC  /* GPIO端口时钟 */
#define LED1_PIN  GPIO_Pin_1           /* 连接到SCL时钟线的GPIO */

#define LED2_PORT     GPIOC               /* GPIO端口 */
#define LED2_CLK      RCC_APB2Periph_GPIOC  /* GPIO端口时钟 */
#define LED2_PIN  GPIO_Pin_2           /* 连接到SCL时钟线的GPIO */

#define LED3_PORT     GPIOC               /* GPIO端口 */
#define LED3_CLK      RCC_APB2Periph_GPIOC  /* GPIO端口时钟 */
#define LED3_PIN  GPIO_Pin_3           /* 连接到SCL时钟线的GPIO */

#define LED4_PORT     GPIOC               /* GPIO端口 */
#define LED4_CLK      RCC_APB2Periph_GPIOC  /* GPIO端口时钟 */
#define LED4_PIN  GPIO_Pin_4           /* 连接到SCL时钟线的GPIO */

#define LED5_PORT     GPIOC               /* GPIO端口 */
#define LED5_CLK      RCC_APB2Periph_GPIOC  /* GPIO端口时钟 */
#define LED5_PIN  GPIO_Pin_5           /* 连接到SCL时钟线的GPIO */

#define LED6_PORT     GPIOC               /* GPIO端口 */
#define LED6_CLK      RCC_APB2Periph_GPIOC  /* GPIO端口时钟 */
#define LED6_PIN  GPIO_Pin_6           /* 连接到SCL时钟线的GPIO */

#define LED7_PORT     GPIOC               /* GPIO端口 */
#define LED7_CLK      RCC_APB2Periph_GPIOC  /* GPIO端口时钟 */
#define LED7_PIN  GPIO_Pin_7           /* 连接到SCL时钟线的GPIO */


typedef enum
{
    LED0 = 0,
    LED1 = 1,
    LED2 = 2,
    LED3 = 3,
    LED4 = 4,
    LED5 = 5,
    LED6 = 6,
    LED7 = 7,
} led_name_t;

void led_init_all(void);                                                    // 初始化所有的LED
void led_init(led_name_t led_name);                                         // 初始化指定的LED
void led_on(led_name_t led_name);                                           // LED打开
void led_off(led_name_t led_name);                                          // LED关闭
void led_toggle(led_name_t led_name);                                       // LED翻转
uint8_t led_get_status(led_name_t led_name);                                // 读取当前LED状态

#endif

子程序bsp_led.c

#include "bsp_led.h"

/// LED参数类型定义
typedef struct
{
    GPIO_TypeDef*  PORT;                                                        ///< LED的PORT口
    const uint32_t CLK;                                                         ///< LED的时钟模块
    const uint16_t PIN;                                                         ///< LED的PIN口     
} led_para_t;

/// LED参数映射表
static led_para_t led_para[LED_NUM] = {
#if (LED_NUM > 0)
    {LED0_PORT,  LED0_CLK,  LED0_PIN},
#endif
#if (LED_NUM > 1)
    {LED1_PORT,  LED1_CLK,  LED1_PIN},
#endif
#if (LED_NUM > 2)
    {LED2_PORT,  LED2_CLK,  LED2_PIN},
#endif
#if (LED_NUM > 3)
    {LED3_PORT,  LED3_CLK,  LED3_PIN},
#endif
#if (LED_NUM > 4)
    {LED4_PORT,  LED4_CLK,  LED4_PIN},
#endif
#if (LED_NUM > 5)
    {LED5_PORT,  LED5_CLK,  LED5_PIN},
#endif
#if (LED_NUM > 6)
    {LED6_PORT,  LED6_CLK,  LED6_PIN},
#endif
#if (LED_NUM > 7)
    {LED7_PORT,  LED7_CLK,  LED7_PIN},
#endif
};

/// LED IO口初始化, 配置成推挽输出
static __INLINE void led_port_init(led_name_t led_name)
{
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(led_para[led_name].CLK, ENABLE);                     // 使能LED的时钟
 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
 
    GPIO_InitStructure.GPIO_Pin   = led_para[led_name].PIN;                     // 设置LED的PIN
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;                           // IO口设为推拉输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;                            // 输出频率最大2MHz,LED应用足矣
    GPIO_Init(led_para[led_name].PORT, &GPIO_InitStructure);                    // 初始化该LED的IO口
  
}

/// 读取LED IO口电平值
static __INLINE uint32_t LED_PORT_LEVEL(led_name_t led_name)
{
 return GPIO_ReadOutputDataBit(led_para[led_name].PORT,led_para[led_name].PIN);
}

/// LED IO口电平置高
static __INLINE void LED_PORT_HIGH(led_name_t led_name)
{
 GPIO_SetBits(led_para[led_name].PORT,led_para[led_name].PIN);
}

/// LED IO口电平置低
static __INLINE void LED_PORT_LOW(led_name_t led_name)
{
 GPIO_ResetBits(led_para[led_name].PORT,led_para[led_name].PIN);
}

/// LED IO口电平翻转
static __INLINE void LED_PORT_TOGGLE(led_name_t led_name)
{
 uint8_t ret;
 ret=GPIO_ReadOutputDataBit(led_para[led_name].PORT,led_para[led_name].PIN);
 if(ret)
  GPIO_ResetBits(led_para[led_name].PORT,led_para[led_name].PIN);
 else
  GPIO_SetBits(led_para[led_name].PORT,led_para[led_name].PIN);
}

/**
  ******************************************************************************
  * @brief  初始化所有的LED灯
  * @param  none
  * @retval none
  ******************************************************************************
  */
void led_init_all(void)
{
    uint8_t i;

    for (i=0; i<LED_NUM; i++)
        led_init((led_name_t)i);
}

/**
  ******************************************************************************
  * @brief  LED灯初始化
  * @param  led_name
  *   @arg  可用值请参考 led_name_t 类型定义中的枚举值
  * @retval none
  ******************************************************************************
  */
void led_init(led_name_t led_name)
{
    led_port_init(led_name);
    led_off(led_name);                                                          // 初始化关闭该LED
}

/**
  ******************************************************************************
  * @brief  LED灯打开
  * @param  led_name
  *   @arg  可用值请参考 led_name_t 类型定义中的枚举值
  * @retval none
  ******************************************************************************
  */
void led_on(led_name_t led_name)
{
#if (LED_LEVEL > 0)
    LED_PORT_HIGH(led_name);
#else
    LED_PORT_LOW(led_name);
#endif
}

/**
  ******************************************************************************
  * @brief  LED灯关闭
  * @param  led_name
  *   @arg  可用值请参考 led_name_t 类型定义中的枚举值
  * @retval none
  ******************************************************************************
  */
void led_off(led_name_t led_name)
{
#if (LED_LEVEL > 0)
    LED_PORT_LOW(led_name);
#else
    LED_PORT_HIGH(led_name);
#endif
}

/**
  ******************************************************************************
  * @brief  LED灯翻转
  * @param  led_name
  *   @arg  可用值请参考 led_name_t 类型定义中的枚举值
  * @retval none
  ******************************************************************************
  */
void led_toggle(led_name_t led_name)
{
    LED_PORT_TOGGLE(led_name);
}

/**
  ******************************************************************************
  * @brief  查询LED当前状态
  * @param  led_name
  *   @arg  可用值请参考 led_name_t 类型定义中的枚举值
  * @retval status. LED状态
  *   @arg  0, LED灯关闭状态
  *   @arg  1, LED灯打开状态
  ******************************************************************************
  */
uint8_t led_get_status(led_name_t led_name)
{
    if (LED_PORT_LEVEL(led_name)) return 0;
    else                          return 1;
}


/********************************************END OF FILE**********************/

5、 运行仿真
  • 方式1:led1亮—延时—led1灭—led2亮—延时—led2灭…
light
  • 方式2:led1亮—延时—led2亮—延时—led3亮—延时…led1灭—延时—led2灭…
light2
6、 遇到的问题及解决措施
  • 问题1:cannot open source input file “stm32f10x_adc.h”: No such file or directory.

  • 解决:添加头文件所在路径到编译器里,以便编译器可以检索到改头文件。

  • 问题2:Not enough information to list load addresses in the image map.
    Not enough information to list load addresses in the image map.

  • 解决:只声明了函数,却未定义函数实体,所以在这个前提下,调用函数时会报这个错误。
    解决方法就是:定义函数实体,或者取消函数调用。

  • 问题:warning: #223-D: function “delay_ms” declared implicitly.

  • 解决:在main.c函数中添加头文件#include “delay.h”

7、总结
  • 在第一个构建工程模板时要尽量仔细一些,不要缺少文件。
  • 在编写程序过程中应该保持严谨的态度,尽量将程序写的更加合理。
  • 遇到报错不要着急,根据报错的信息认真分析可能出错的原因,如果无法解决可以上网搜索相关资料,问题解决后应该做好记录。
  • 实验过后认真总结,分析实验过程遇到的问题,养成良好的实验习惯。
参考

[keil5+proteus8.6联调环境搭建_sl……的博客-CSDN博客_keil5与proteus联调]

  • 12
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值