STM32

STM32是STMicroelectronics(意法半导体)推出的一系列基于ARM Cortex-M内核的32位微控制器(MCU)产品。这些微控制器提供了广泛的产品系列,覆盖了多种不同的性能和功能需求,适用于各种应用领域,包括工业控制、汽车电子、消费类电子、医疗设备等。

STM32系列微控制器以其高性能、低功耗、丰富的外设接口和灵活的开发工具而闻名。它们通常具有丰富的存储器、多种通信接口(如UART、SPI、I2C、CAN等)、模拟数字转换器(ADC)、定时器、PWM输出等功能,以满足不同应用场景下的需求。

STM32微控制器通常使用标准的ARM Cortex-M内核,包括Cortex-M0、M0+、M3、M4和M7等,这些内核具有不同的性能和功耗特性,可根据具体应用的需求进行选择。此外,STM32系列还提供了多种封装和引脚配置,以满足不同尺寸和集成度的要求。

STMicroelectronics为STM32系列提供了丰富的开发工具和支持资源,包括基于ARM开发环境的集成开发环境(IDE)、调试器、评估板和参考设计等。这些工具和资源有助于开发人员快速开发和部署他们的应用,并提供了全面的技术支持和文档资料,帮助用户充分发挥STM32微控制器的性能和功能优势。

很多初学的小伙伴认为STM32是从main函数开始执行,其实在main之前还有一个“启动”过程,下面分享一下在启动过程的那些内容。

基础

首先,你要知道STM32启动启动流程,你就需要掌握一点汇编基础知识。

汇编语言属于机器语言,或者说低级语言,C语言属于高级语言,所以,汇编和C语言在语法上差异很大。

如果你学底层开发,汇编的一些基础知识需要掌握。不需要精通,但需要看懂常见的汇编代码。

说明

STM32的启动文件与编译器有关,不同编译器,它的启动文件不同。

虽然启动文件(汇编)代码各有不同,但它们原理类似,都属于汇编程序。

我们拿基于Keil MDK的启动文件(.s)来举例,说一下要点内容。

分配堆栈

在基于MDK的启动文件开始,有一段汇编代码是分配堆栈大小的。

“STM32真的是从main开始执行的吗?"

这里重点知道堆栈数值大小就行。还有一段AREA(区域),表示分配一段堆栈数据段。

数值大小可以自己修改,也可以使用STM32CubeMX数值大小配置:

“STM32真的是从main开始执行的吗?"

在IAR中,是通过工程配置堆栈大小:

“STM32真的是从main开始执行的吗?"

向量表

相信大家都知道向量表,先看汇编代码:

“STM32真的是从main开始执行的吗?"

这个向量表就是对应手册中的那些内容:

“STM32真的是从main开始执行的吗?"

我们需要知道这个地方中的复位,程序上电之后,是跳到Reset_Handler这个位置。

执行代码

上面知道代码是从Reset_Handler开始执行,我们看Reset_Handler汇编代码:

“STM32真的是从main开始执行的吗?"

在启动的时候,执行了SystemInit这个函数。

之前标准外设库在SystemInit这个函数初始化了系统时钟,后面HAL库单独把那部分代码提出来了。

执行完SystemInit函数,就跳转到我们的main函数执行了。

来源:嵌入式专栏
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 442

今天就再来分享一下关于Assert的内容。

1、写在前面

有经验的工程师都知道,随着软件版本的迭代,或者需求不断变更,我们的代码就会变得越来越“臃肿”。

在编码的过程中,如果没有注重一些细节,你的代码就可能存在许多隐藏的Bug。

那么,我们如何找出这些隐藏的Bug呢?

今天就说其中的一点:Assert断言。

2、关于Assert断言

什么是Assert断言?

编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式。

断言表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真。

可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言,而在部署时禁用断言。

同样,程序投入运行后,最终用户在遇到问题时可以重新启用断言。

---来自百度百科

这里的概念,可能不好理解,简单举一个例子来说明吧。

有这么一个数组和函数:

int Array[5] = {0xA1, 0xB2, 0xC3, 0xD4, 0xE5};

int Fun(char i)
{
    return Array[i];
}

如果我们函数中不加Assert断言语句,你觉得直接调用会这个函数会有风险吗?

假如这么调用:

int a;

a = Fun(8);

很明显,就这么调用,会出错,且我们不容易发现错误在哪里。

但是,假如添加有Assert断言语句,错误就能一下找出来。

3、Assert断言实际应用

其实,Assert断言在很多标准的代码中,基本都有。我们还是拿STM32的代码来说明吧。

不管是STM32标准外设库、还是HAL、LL库源代码里面都有Assert断言机制。

不知道大家有没有注意过assert_param函数?

1)拿STM32最常见的GPIO初始化函数为例

A、标准外设库GPIO初始化:

“STM32函数库Assert断言机制"

B、HAL库GPIO初始化:

“STM32函数库Assert断言机制"

相信大家都看到过STM32库中的参数断言语句,他的作用就是用于检查函数传入参数是否正确。

2)STM32参数断言使能

STM32的assert_param参数断言函数是没有使能的,如下:

#define assert_param(expr) ((void)0)

也就是assert_param不起作用。

如果需要使用,就需要对其使能才行。

A、标准外设库

“STM32函数库Assert断言机制"

B、HAL库

道理一样,使能ASSERT,可以手动:

#define USE_FULL_ASSERT    1U

也可以通过STM32CubeMX配置:

“STM32函数库Assert断言机制"

3)代码大小

添加Assert断言之后,代码量肯定要增加,比如:

不使能assert_param代码量:

Code=5350 RO-data=360 RW-data=16 ZI-data=1152

使能assert_param:

Code=8300 RO-data=362 RW-data=16 ZI-data=1152

4)断言失败处理

断言失败,可根据实际项目需求,做出一定处理。比如:打印错误信息,存储错误日志等。

来源:嵌入式专栏
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:
cathy@eetrend.com)。

围观 257

嵌入式初学者入门的第一个“项目”就是LED点灯,那么,本文带你看看51、STM32、Linux点灯有什么区别?

51点灯

51点灯,是很多单片机初学者的首选,难度也是相对比较低的。

准备工作:

  • 51开发板(以STC51单片机为例)

  • Keil C51、STC-ISP下载软件

51单片机开发,通常是直接操作寄存器,比如P1_0对应LED的IO口。

源代码:

#include <reg51.h>

sbit LED = P1^0;

void main()
{
    LED = 0;

    while(1);
}

STM32点灯

相对于51点灯,STM32点灯难度系数要大一点,因为STM32外设资源更多,启动文件更复杂,很多新手看到之后直接就放弃了。

其实,也很简单,下面分别通过寄存器和标准外设库点灯,你就知道明白了。

准备工作:

  • STM32开发板

  • Keil MDK、ST-LINK Utility下载软件

1.寄存器版本

直接操作寄存器,需要深入理解每个寄存器每个bit位的含义(不建议初学者一开始就学寄存器),而且,源码看起来比较多:

#include "stm32f4xx.h"

/* 主函数*/
int main(void)
{
    /*开启 GPIOH 时钟,使用外设时都要先开启它的时钟*/
    RCC_AHB1ENR |= (1<<7);

    /* LED 端口初始化 */
    /*GPIOH MODER10 清空*/
    GPIOH_MODER &= ~( 0x03<< (2*10));

    /*PH10 MODER10 = 01b 输出模式*/
    GPIOH_MODER |= (1<<2*10);

    /*GPIOH OTYPER10 清空*/
    GPIOH_OTYPER &= ~(1<<1*10);

    /*PH10 OTYPER10 = 0b 推挽模式*/
    GPIOH_OTYPER |= (0<<1*10);

    /*GPIOH OSPEEDR10 清空*/
    GPIOH_OSPEEDR &= ~(0x03<<2*10);

    /*PH10 OSPEEDR10 = 0b 速率 2MHz*/
    GPIOH_OSPEEDR |= (0<<2*10);

    /*GPIOH PUPDR10 清空*/
    GPIOH_PUPDR &= ~(0x03<<2*10);

    /*PH10 PUPDR10 = 01b 上拉模式*/
    GPIOH_PUPDR |= (1<<2*10);

    /*PH10 BSRR 寄存器的 BR10 置 1,使引脚输出低电平*/
    GPIOH_BSRR |= (1<<16<<10);  //点灯

    while (1);
}

.标准外设库版本

标准外设库,就是ST官方已经把寄存器进行封装过一次,你直接调用函数借口即可。

#include "stm32f10x.h"

/*  LED时钟端口、引脚定义*/
#define LED_PORT       GPIOC   
#define LED_PIN       GPIO_Pin_0
#define LED_PORT_RCC            RCC_APB2Periph_GPIOC

void LED_Init()
{
    GPIO_InitTypeDef GPIO_InitStructure;        //定义结构体变量

    RCC_APB2PeriphClockCmd(LED_PORT_RCC, ENABLE);

    GPIO_InitStructure.GPIO_Pin = LED_PIN;                //选择你要设置的IO口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //设置推挽输出模式
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;       //设置传输速率
    GPIO_Init(LED_PORT,&GPIO_InitStructure);              //初始化GPIO 

    GPIO_SetBits(LED_PORT, LED_PIN);                       //将LED端口拉高,熄灭LED
}

int main()
{  
  LED_Init();
  GPIO_ResetBits(LED_PORT,GPIO_Pin_0);//点灯

    while(1);
}

Linux点灯

Linux点灯,相对来说就更复杂了。当然,有一些已经搭建好的环境,就相对简单一点,也比较容易。如果自己一步一步移植系统、写驱动···就很复杂。

1.树莓派

我们这里以【开源库wiringPi】为例:

1、下载U-boot源码,配置、编译;

2、下载Linux内核、配置、编译(一般开发板都会有现成的配置文件);

3、制作跟文件系统;(以上三个步骤,如果没有一定的Linux基础,可以使用一键烧写)

4、移植开源库WiringPi;

5、查看电路图找到LED对应的引脚,程序需要用到引脚号;

6、编码、交叉编译;

7、下载运行。

准备工作做好之后,点灯的源码就比较简单:

#include <wiringPi.h>

int main(void)
{
    wiringPiSetup() ;
    pinMode (7, OUTPUT);
    gitalWrite(7, HIGH);
    while(1);
}

2.Linux驱动点灯

在所有的点灯方法中,这个方法难度系数极高,涵盖了嵌入式开发从上层应用到底层驱动。步骤涉及了驱动代码编写、Linux内核模块添加、移植操作系统、Linux应用程序编写。

这里分享一下mini2440经典LED驱动源码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/ioctl.h>
#include <linux/gpio.h> 
#include <mach/regs-gpio.h> 
#include "led.h" 

static int led_open(struct inode *inode, struct file *file)
{  
    s3c2410_gpio_cfgpin(S3C2410_GPB(5), S3C2410_GPIO_OUTPUT);
    s3c2410_gpio_setpin(S3C2410_GPB(5), 1);   
    return 0;
} 

static int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{  
    switch (cmd) {  
        case LED_ON:    
            s3c2410_gpio_setpin(S3C2410_GPB(5), 0);    
            return 0;  
        case LED_OFF:    
            s3c2410_gpio_setpin(S3C2410_GPB(5), 1);    
            return 0;  
        default:    
            return -EINVAL;  
        }
} 

static struct file_operations led_fops = {  
    .owner = THIS_MODULE,  
    .open = led_open,  
    .ioctl = led_ioctl,
}; 

static struct miscdevice led_misc = {  
    .minor = MISC_DYNAMIC_MINOR,  
    .name = "led",  
    .fops = &led_fops,
}; 

static int led_init(void){  
    return misc_register(&led_misc);
} 

static void led_exit(void){  
    misc_deregister(&led_misc);
} 

MODULE_LICENSE("Dual BSD/GPL");
module_init(led_init);
module_exit(led_exit);

驱动写了,然后就是应用层代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include "led.h" 

int main(void){        
    int fd;         
    fd = open("/dev/led", O_RDWR);         
    if (fd < 0) {                
        printf("No such device!\n");                
        return -1;        
    }         
    while (1) {                
        ioctl(fd, LED_ON);                
        sleep(1);                
        ioctl(fd, LED_OFF);                
        sleep(1);        
        }         

    close(fd);         
    return 0;
}

最后

点灯是基础,如果你从事嵌入式开发,我觉得这些点灯是最基础的第一步。

可能第一步很难,但走过第一步,相信下一步就会变得更容易。

来源:嵌入式专栏
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 138

SPWM(Sinusoidal PWM)法是一种比较成熟的,目前使用较广泛的PWM法。SPWM法就是以该结论为理论基础,用脉冲宽度按正弦规律变化而和正弦波等效的PWM波形即SPWM波形控制逆变电路中开关器件的通断,使其输出的脉冲电压的面积与所希望输出的正弦波在相应区间内的面积相等,通过改变调制波的频率和幅值则可调节逆变电路输出电压的频率和幅值。本文主要详解stm32产生spwm原理及程序,首先来了解一下生成SPWM波的基理是什么,具体得跟随小编一起来了解一下。

生成SPWM波的基理

由于正弦交流量是典型的模拟量,传统发电机难以完成高频交流电流输出,而功率半导体器件于模拟状态工作时产生的动态损耗剧增,于是,用开关量取代模拟量成为必由之路,并归结为脉冲电路的运行过程,从而构成了运动控制系统中的功率变换器或电源引擎。典型的H桥逆变电路很容易理解(图1a)

“一文解析STM32产生spwm原理及程序"

对角联动的两个开关器件和与之对应的另一组对角桥臂同时实施交替的开关作业时,建立运行后,流经负载的电流即为交流电流(图1b),考虑到功率器件关断时的滞后特性避免造成短路,通常都做成(图1c)的波形结构。显然开关器件输出的是方波(矩形波)交流电流。
  
在交流应用场合,多数负载要求输入的是正弦波电流。
  
电工学认为,周期性的非正弦交流量是直流、正弦波和余弦波等分量的集合,或者是非正弦波也可以分解为相位差和频率不同的正弦波以及直流分量。
  
不良波形或失真严重的正弦交流量必然产生大量的低次、高次及分数谐波,丰富的谐波分量与基波叠加的情景使得正负峰值几乎同时发生,换向突变时急剧的运动状态将对负载造成冲击并导致负载特性的不稳定或漂移,又加重了滤波器件的负担,损耗也随之增大,非但降低了电网的功率因数,还对周边设备造成不良影响。
  
在高频化和大功率电力变换场合,装置内部急剧的电流变化,不但使器件承受很大电磁应力,并向装置周围空间辐射有害电磁波污染环境,这种电磁干扰(Electro Magnetic Interference简称EMI)还会引发周围设备的误动作及造成电能计量紊乱。抑制谐波和EMI的防御仍为重要课题或技术指标。
  
可见,简单的方波在功率应用场合下显示出了不尽如人意的一面。当然,在不触及负载特性、能量转换效率、环境污染和系统综合技术指标以及小功率应用场合的前提下,就控制方法而言则显得容易些。
  
自然采样法是一种基于面积等效理念的能量转换形式,其原理极为简单而且直观,并具备十分确切的数理依据,通用性及可操作性也很强。当正弦基波与若千个等幅的三角载波在时间轴上相遇时,并令正弦波的零点与三角波的峰点处于同相位(图2a),所得的交点(p)表达为时间意义上的相位角和对应的瞬时幅值,交点间的相位区间段表示以正弦部分为有效输出的矩形脉冲群(图2b)。
  

“一文解析STM32产生SPWM原理及程序"

由此,SPWM波的基本概念是每一周期的基波与若千个载波进行调制(载波的数量与基波之比即为载波比),并依次按正弦函数值定位的有效相位区间集合成等幅不等宽且总面积等效于正弦量平均值的正弦化脉冲序列。对应于正弦量的正负半周,实施双路调制或单路分相处理及放大后,控制驱动功率开关器件运行,最终得正弦化交流量的样本波形如(图3)所示,滤波后流经负载的电流即为正弦波电流。
  

“一文解析STM32产生SPWM原理及程序"

stm32产生spwm原理及程序

SPWM波的形成原理

利用正弦波的各点幅值成正弦变换的思想,我们可以类似的采取在一系列方波中,让占空比中高度不变,占空比大小呈正弦变换的这样的一种做法,这样占空比大小呈正弦变换的波我们称之为SPWM波。网上有生成正弦波采样点数组的软件,可以选择采样点数和精度。本次实验中就需要用这个软件来产生我们需要的正弦表。

STM32产生SPWM程序

“一文解析STM32产生SPWM原理及程序"

“一文解析STM32产生SPWM原理及程序"

“一文解析STM32产生SPWM原理及程序"

“一文解析STM32产生SPWM原理及程序"

来源:网络
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:
cathy@eetrend.com)。

围观 900

GPIO是通用输入/输出端口的简称,是STM32可控制的引脚。GPIO的引脚与外部硬件设备连接,可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。

STM32F103ZET6芯片为144脚芯片,包括7个通用目的的输入/输出口(GPIO)组,分别为GPIOA、GPIOB、GPIOC、GPIOD、GPIOE、GPIOF、GPIOG,同时每组GPIO口组有16个GPIO口。通常简略称为PAx、PBx、PCx、PDx、PEx、PFx、PGx,其中x为0-15。

STM32的大部分引脚除了当GPIO使用之外,还可以复用为外设功能引脚,比如串口。

GPIO基本结构

每个GPIO内部都有这样的一个电路结构,这个结构在本文下面会具体介绍。

“STM32的GPIO电路原理"

保护二极管:IO引脚上下两边两个二极管用于防止引脚外部过高、过低的电压输入。当引脚电压高于VDD时,上方的二极管导通;当引脚电压低于VSS时,下方的二极管导通,防止不正常电压引入芯片导致芯片烧毁。但是尽管如此,还是不能直接外接大功率器件,须加大功率及隔离电路驱动,防止烧坏芯片或者外接器件无法正常工作。

P-MOS管和N-MOS管:由P-MOS管和N-MOS管组成的单元电路使得GPIO具有“推挽输出”和“开漏输出”的模式。这里的电路会在下面很详细地分析到。

TTL肖特基触发器:信号经过触发器后,模拟信号转化为0和1的数字信号。但是,当GPIO引脚作为ADC采集电压的输入通道时,用其“模拟输入”功能,此时信号不再经过触发器进行TTL电平转换。ADC外设要采集到的原始的模拟信号。

这里需要注意的是,在查看《STM32中文参考手册V10》中的GPIO的表格时,会看到有“FT”一列,这代表着这个GPIO口时兼容3.3V和5V的。如果没有标注“FT”,就代表着不兼容5V。
STM32的GPIO工作方式

GPIO支持的输入输出模式:

  • GPIO_Mode_AIN 模拟输入

  • GPIO_Mode_IN_FLOATING 浮空输入

  • GPIO_Mode_IPD 下拉输入

  • GPIO_Mode_IPU 上拉输入

  • GPIO_Mode_Out_OD 开漏输出

  • GPIO_Mode_Out_PP 推挽输出

  • GPIO_Mode_AF_OD 复用开漏输出

  • GPIO_Mode_AF_PP 复用推挽输出

每个I/O口可以自由编程,但I/O口寄存器必须按32位字被访问。

下面将具体介绍GPIO的这八种工作方式:

浮空输入模式

“STM32的GPIO电路原理"

浮空输入模式下,I/O端口的电平信号直接进入输入数据寄存器。也就是说,I/O的电平状态是不确定的,完全由外部输入决定;如果在该引脚悬空(在无信号输入)的情况下,读取该端口的电平是不确定的。

上拉输入模式

“STM32的GPIO电路原理"

上拉输入模式下,I/O端口的电平信号直接进入输入数据寄存器。但是在I/O端口悬空(在无信号输入)的情况下,输入端的电平可以保持在高电平;并且在I/O端口输入为低电平的时候,输入端的电平也还是低电平。

下拉输入模式

“STM32的GPIO电路原理"

下拉输入模式下,I/O端口的电平信号直接进入输入数据寄存器。但是在I/O端口悬空(在无信号输入)的情况下,输入端的电平可以保持在低电平;并且在I/O端口输入为高电平的时候,输入端的电平也还是高电平。

模拟输入模式

“STM32的GPIO电路原理"

模拟输入模式下,I/O端口的模拟信号(电压信号,而非电平信号)直接模拟输入到片上外设模块,比如ADC模块等等。

开漏输出模式

“STM32的GPIO电路原理"

开漏输出模式下,通过设置位设置/清除寄存器或者输出数据寄存器的值,途经N-MOS管,最终输出到I/O端口。这里要注意N-MOS管,当设置输出的值为高电平的时候,N-MOS管处于关闭状态,此时I/O端口的电平就不会由输出的高低电平决定,而是由I/O端口外部的上拉或者下拉决定;当设置输出的值为低电平的时候,N-MOS管处于开启状态,此时I/O端口的电平就是低电平。同时,I/O端口的电平也可以通过输入电路进行读取;注意,I/O端口的电平不一定是输出的电平。

开漏复用输出模式

“STM32的GPIO电路原理"

开漏复用输出模式,与开漏输出模式很是类似。只是输出的高低电平的来源,不是让CPU直接写输出数据寄存器,取而代之利用片上外设模块的复用功能输出来决定的。

推挽输出模式

“STM32的GPIO电路原理"

推挽输出模式下,通过设置位设置/清除寄存器或者输出数据寄存器的值,途经P-MOS管和N-MOS管,最终输出到I/O端口。这里要注意P-MOS管和N-MOS管,当设置输出的值为高电平的时候,P-MOS管处于开启状态,N-MOS管处于关闭状态,此时I/O端口的电平就由P-MOS管决定:高电平;当设置输出的值为低电平的时候,P-MOS管处于关闭状态,N-MOS管处于开启状态,此时I/O端口的电平就由N-MOS管决定:低电平。同时,I/O端口的电平也可以通过输入电路进行读取;注意,此时I/O端口的电平一定是输出的电平。

推挽复用输出模式

“STM32的GPIO电路原理"

推挽复用输出模式,与推挽输出模式很是类似。只是输出的高低电平的来源,不是让CPU直接写输出数据寄存器,取而代之利用片上外设模块的复用功能输出来决定的。

总结与分析

什么是推挽结构和推挽电路?

推挽结构一般是指两个参数相同的三极管或MOS管分别受两互补信号的控制,总是在一个三极管或MOS管导通的时候另一个截止。高低电平由输出电平决定。

推挽电路是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务。电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小、效率高。输出既可以向负载灌电流,也可以从负载抽取电流。推拉式输出级既提高电路的负载能力,又提高开关速度。
开漏输出和推挽输出的区别?

开漏输出:只可以输出强低电平,高电平得靠外部电阻拉高。输出端相当于三极管的集电极。适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内)。

推挽输出:可以输出强高、低电平,连接数字器件。

关于推挽输出和开漏输出,最后用一幅最简单的图形来概括:

“STM32的GPIO电路原理"

该图中左边的便是推挽输出模式,其中比较器输出高电平时下面的PNP三极管截止,而上面NPN三极管导通,输出电平VS+;当比较器输出低电平时则恰恰相反,PNP三极管导通,输出和地相连,为低电平。右边的则可以理解为开漏输出形式,需要接上拉。

在STM32中选用怎样选择I/O模式?

  • 浮空输入_IN_FLOATING ——浮空输入,可以做KEY识别,RX1

  • 带上拉输入_IPU——IO内部上拉电阻输入

  • 带下拉输入_IPD—— IO内部下拉电阻输入

  • 模拟输入_AIN ——应用ADC模拟输入,或者低功耗下省电

  • 开漏输出_OUT_OD ——IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变。可以读IO输入电平变化,实现C51的IO双向功能

  • 推挽输出_OUT_PP ——IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的

  • 复用功能的推挽输出_AF_PP ——片内外设功能(I2C的SCL、SDA)

  • 复用功能的开漏输出_AF_OD——片内外设功能(TX1、MOSI、MISO.SCK.SS)

来源:STM32嵌入式开发
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:
cathy@eetrend.com)。

围观 133

新建工程文件夹

建立名字为LED的文件夹存放工程文件,其中再建立两个文件夹,Listing文件夹用于存放编译器编译时候产生的C语言、汇编、链接文件,Output文件夹用于存放编译产生的调试信息、hex文件、预览信息、封装库等。

文件夹建好之后,在LED文件夹下存放startup_stm32f10x_hd.s、stm32f10x.h、main.c文件。前两个文件可以在STM32F1xx的固件库中找到,第三个文件是空文件。

在Keil5中新建工程的步骤

如下图所示,Project-New,新建工程,工程名为Led,点击保存。

“Keil5软件配置与新建STM32工程的步骤"

点击保存之后,弹出如下窗口,选择芯片型号。根据你开发板使用的芯片具体的型号来选择。如果这里没有出现你想要的CPU型号,或者一个型号都没有,那么肯定是你的KEIL5没有添加Device库,关于如何添加请往下看。

“Keil5软件配置与新建STM32工程的步骤"

安装Device库

下载KEIL MDK5以后是没有安装device的,如果此时创建工程会找不到目标芯片,如下图所示:

“Keil5软件配置与新建STM32工程的步骤"

此时我们就要安装自己需要的芯片系列,比如STM32F1系列。首先选择Project-Manage-Pack Installer,此时出现下面如下界面:

“Keil5软件配置与新建STM32工程的步骤"

选择菜单栏中的Packs,点击Check for Updates,此时就会出现最新的支持的CPU系列,更新完毕之后会出现如下界面:

“Keil5软件配置与新建STM32工程的步骤"

我们选择需要安装的芯片厂商,这里因为要安装STM32F1系列,所以选择ST公司,然后在右侧出现了STM系列的芯片,如上图右侧箭头所示,此时点击需要安装的STM32系列,这里我需要安装的是STM32F1系列,点击安装,此时软件会下载对应的芯片包,如下图所示:

“Keil5软件配置与新建STM32工程的步骤"

这个下载过程比较慢,耐心等待,安装完毕之后,关闭KEIL5,重新打开KEIL5,此时新建工程,就出现了需要的芯片。

用寄存器控制 STM32 时我们不需要在线添加库文件,如关掉下图窗口。

“Keil5软件配置与新建STM32工程的步骤"

向工程中添加文件

在新建的工程中添加文件,文件从本地建好的工程文件夹下获取,双击组文件夹就会出现添加文件的路径,然后选择文件即可,如下图所示。

“Keil5软件配置与新建STM32工程的步骤"

Keil5软件配置

配置魔术棒

如下图所示,Target中选中微库“Use MicroLib”,为了编写串口驱动时可以使用printf函数。

“Keil5软件配置与新建STM32工程的步骤"

Output 选项卡中把输出文件夹定位到我们工程目录下的 output 文件夹,如果想在编译的过程中生成 hex 文件,那么那 Create HEX File 选项勾上。

“Keil5软件配置与新建STM32工程的步骤"

点击Listing选项卡中的Select Folder for Listings,把输出文件夹定位到先前创建的Listings文件夹。

“Keil5软件配置与新建STM32工程的步骤"

配置下载器

在仿真器连接好电脑和开发板且开发板供电正常的情况下,打开KEIL5软件,在魔术棒选项卡里面选择所用仿真器的型号,如下图所示。

“Keil5软件配置与新建STM32工程的步骤"

在Utilities中勾选Use Debug Driver,如下图所示。

“Keil5软件配置与新建STM32工程的步骤"

点击Debug中的Settings,选择相应仿真器,勾选SW,Clock选为5MHz,Reset选择Autodetect。

“Keil5软件配置与新建STM32工程的步骤"

在Flash Download中做如下图所示的配置,勾选Reset and run,程序下载后自动运行,不用先手动复位。

“Keil5软件配置与新建STM32工程的步骤"

Keil5下载程序

如上,在Keil5中新建了工程,并对软件进行了正确配置之后,就可以点击下图1处的Rebuild按钮编译,再点击2处的LOAD下载到开发板上运行。

“Keil5软件配置与新建STM32工程的步骤"

来源:STM32嵌入式开发
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 901

IAP是什么

有时项目上需要远程升级单片机程序,此时需要接触到IAP编程。

IAP即为In Application Programming,解释为在应用中编程,用户自己的程序在运行过程中对User Flash的部分区域进行烧写。即是一种对单片机Flash擦写的一种编程方案。

通常情况下,一片STM32单片机的Flash只有一个用户程序,而IAP编程则是将单片机的Flash分成至少两大区域,一部分叫做bootloader区,一部分叫做app用户代码区,还可留出一部分区域为代码备份区。

IAP的应用场所

通常情况下我们给STM32单片机烧录更新程序时是通过SWD、J-link或者通过设置BOOT引脚后,使用串口进行程序下载,这样的方式直接一次性将程序文件下载到单片机的Flash中,比较适合绝大部分的应用。

但是当产品投入实际应用时,封装完成后在后期的使用过程中遇到某些程序上的bug或者是根据客户需求需要增加一些功能的时候,使用传统代码烧录的方法就可能需要拆除封装,而使用IAP编程在bootloader区提前写入与外部通信的接口用于升级单片机代码,使得我们不用对已完成包装的产品进行拆除既可以更新代码,这样既节约了成本,也更加方便快捷。

IAP编程的流程

IAP编程将Flash区分成的两个区域,bootloader区和app用户代码区具有截然不同的功能。

bootloader区,主要实现接收程序文件,并将该程序写于特定位置的Flash区域。而这里接收外部程序文件,就需要实时和外部通信了。STM32单片机与外部通信大多是通过自身的串口接收和发送数据,不过STM32单片机的串口可以外接多种通讯接口,例如422、485、GPRS及ESP8266等。即我们可以通过串口外接蓝牙模块、WiFi模块或者是其他网络模块,就可以实现远程的文件传送更新单片机程序了。

app用户代码区则是主要实现我们所需要的功能操作,除此之外app用户代码区还需要实时检查代码运行情况,通过判断更新程序的标志位来判断是否需要升级程序。若是需要升级程序则进入bootloader区进行代码更新;若不需要则继续运行功能函数代码即可。

因此IAP编程下的单片机运行流程如下图:

“STM32代码远程升级之IAP编程"

根据运行流程,我们可以总结出简单几条bootloader设计过程中需要注意的地方:

  • 精简、程序尽可能精简。在单片机Flash有限的情况下,bootloader代码占用Flash的空间越小,则APP程序代码就可占用更多,实现更多功能函数。
  • 标志位不受复位的影响。
  • Bootloader中尽量不使用中断。

来源:STM32嵌入式开发
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 169

页面

订阅 RSS - STM32