Proteus 仿真软件
安装请自行到网上寻找资源b站友情链接。
我这里使用的是已经汉化过的,可能会出现bug建议使用英文原版。
并且再提及一下,千万不要把Proteus安装在有含有中文路径的文件夹下!!!
新建工程
主页左上角点击新建工程。
输入项目名称,
输入路径。千万不要使用带有中文的路径,不然会在后面无法进行
选择新工程(new project)。
然后下一步(next)。
新建工程向导。
选择从选中的模板创建原理图。
可选择DEFAULT,或者不选也行。
下一步(next)。
选择不创建新的PCB布版设计。
下一步(next)。
到了很麻烦的地方了。
接下来应选择创建固件项目,然后选择你需要的东西,**但是,**因为我用了带有中文的路径。所以现在是无法选择是灰色的。
所以这里我退出了Proteus然后将Proteus删除并重新安装Proteus(真的很麻烦,所以千万切记)。
再重复如上步骤。
你就能看到可以选择的项目了,接下来选择你需要的组件。
这里我使用的是Cortex-M3的内核,STM32F103R6的控制器,编译器在右方选择 Keil for 8051 和 Keil for ARM ,这里需要你先下载Keil uVision5并安装 C51 和 ARM ,详细的安装教程放在链接里➡友情链接。
然后选择检查全部,等它显示下面的样式就说明成功了。
点击确定。
下一步。
完成了。
你就会看见如下。
制作电路
(1) 点击图中所示的“P”,则出现对话框“选择元器件(Pick Devices)”,可以选择相应的元器件后点
击“OK”,比如:可以在“关键词(Keywords)”文本框中输入“LED”,在中间出现很多器件,选择相应器件。
LED示例。
RES(电阻)示例。
(2)将相应元器件放完之后,联系,组成实验系统。
在搭建完电路后,点击左下角三角形符号
开始编译。
这里我出现了一个bug:
解决办法在参考博客里。
后来再一次运行时仍然出现了这个错误,在研究了proteus的使用后,我意思到自己并没有导入.hex文件,自然就无法编译。
此处是操作步骤:
双击U1(即芯片)
将我们在keil5中生成的.hex文件放进程序文件(Program File)中。
然后选择晶振的频率为8M。
这时候我们再重新编译,
成功了。
LED灯如我们程序中所写的那样,正以50ms的频率亮灭。
实验
接下来我们实现如下要求:
画出 8 个 LED,实现由上到下 LED 依次点亮与熄灭,延时时间为50ms。
按如下电路图接线(此处我采用了三种不同颜色的LED灯,不必和演示电路图完全一致,可自行发挥。)
接下来我们在KEIL5里编写bsp_led.h文件。
代码如下:
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
{
LED1 = 0,
LED2 = 1,
LED3 = 2,
LED4 = 3,
LED5 = 4,
LED6 = 5,
LED7 = 6,
LED8 = 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_para[led_name].PIN
}
/// 读取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**********************/
main.c文件
#include "stm32f10x.h"
#include "delay.h"
#include "bsp_led.h"
#include "key.h"
void key_scan(void);
int main(void)
{
/*定义变量*/
/*初始化硬件接口*/
led_init_all(); //初始化与LED连接的硬件接口
while(1)
{
//方法一:
uint8_t i;
led_on((led_name_t)0);
delay_ms(5);
led_off((led_name_t)0);
delay_ms(5);
led_on((led_name_t)1);
delay_ms(5);
led_off((led_name_t)1);
delay_ms(5);
led_on((led_name_t)2);
delay_ms(5);
led_off((led_name_t)2);
delay_ms(5);
led_on((led_name_t)3);
delay_ms(5);
led_off((led_name_t)3);
delay_ms(5);
led_on((led_name_t)4);
delay_ms(5);
led_off((led_name_t)4);
delay_ms(5);
led_on((led_name_t)5);
delay_ms(5);
led_off((led_name_t)5);
delay_ms(5);
led_on((led_name_t)6);
delay_ms(5);
led_off((led_name_t)6);
delay_ms(5);
led_on((led_name_t)7);
delay_ms(5);
led_off((led_name_t)7);
delay_ms(5);
//方法2:
// led_on(LED1);
// delay_ms(50);
// led_off(LED1);
// delay_ms(50);
// led_on(LED2);
// delay_ms(50);
// led_off(LED2);
// delay_ms(50);
// led_on(LED3);
// delay_ms(50);
// led_off(LED3);
// delay_ms(50);
// led_on(LED4);
// delay_ms(50);
// led_off(LED4);
// delay_ms(50);
// led_on(LED5);
// delay_ms(50);
// led_off(LED5);
// delay_ms(50);
// led_on(LED6);
// delay_ms(50);
// led_off(LED6);
// delay_ms(50);
// led_on(LED7);
// delay_ms(50);
// led_off(LED7);
// delay_ms(50);
// led_on(LED8);
// delay_ms(50);
// led_off(LED8);
// delay_ms(50);
}
}
这里我为了让LED亮灭得快一点所以设置的为5ms,建议自己写的时候改为50。
效果:
Proteus 8 - 原理图绘制
这样我们就完成了8个LED灯的依次亮灭要求。