STM32 规范工程建立

发布者:EtherealJourney最新更新时间:2016-10-11 来源: eefocus关键字:STM32  规范工程建立 手机看文章 扫描二维码
随时随地手机看文章
我接触过很多STM32工程,无论是开发板自带、网上大牛的还是官方的,它们的工程布局说实话其实还是不错的,但是毕竟是人家的工程,使用起来总是感到有点陌生,老给人一种二手的感觉。所以决定新建一个属于自己风格的工程,并把它奉为自己专用标准的工程模板。这个工程模板自己已经用了好几年了,每当从网上下载到新的代码时,我总是要将它转变成自己的代码然后添加进自己的工程,期间工程也不断的改进过还几次。现在觉得自己的工程可以拿得出手了,所以在这里分享给大家,最起码有个参考作用!
1、工程组的划分
我的工程分成5个组(Group),分别是:APP、BSP、CMISIS、StartUp、STM32F10x_StdPeriph_Driver。如图所示。
STM32 规范工程建立 - ziye334 - ziye334的博客
APP组里包含应用相关的一些代码以及一些配置文件也可存放到这个组中。
BSP组主要是放置一些跟硬件相关的代码文件,如驱动文件等。
CMSIS组存放更Cortex-M3内核相关的文件。
StartUp组里存放启动文件。
STM32F10x_StdPeriph_Driver组存放着的是STM32的库文件。
2、文件的布局
既然已经知道了工程组的划分,则实际工程需要新建与组相同布局的文件夹,同时还要新建一个名为Proj的文件夹,如图所示:
STM32 规范工程建立 - ziye334 - ziye334的博客
除了Proj和StartUp文件外,还需要在每个 文件夹中新建两个文件夹分别取名为:inc和src,如图所示:
STM32 规范工程建立 - ziye334 - ziye334的博客
 Proj文件夹除了存放着工程文件外,还需要新建两个文件夹:list和obj两个文件,分别存放工程项目生成的列表文件与目标文件。如图所示:
STM32 规范工程建立 - ziye334 - ziye334的博客
 怎么新建keil工程不说,不过这么改变list文件和obj文件的目录有必要讲下:点击Project-->Options for Target就会出现一个配置框,选择Output页,点击Select Folder for Objects按钮,选择我们之前新建的obj目录作为输出目录;再选择Listing页,点击Select Folder for Listing按钮,选择刚新建的list目录。
在APP文件夹中src文件夹必须新建一个main.c文件存放主函数代码!除此之外还需要stm32f10x_it.c存放中断服务程序代码,这个文件是官方提供的不需要自己编写!如下图:
STM32 规范工程建立 - ziye334 - ziye334的博客
在APP文件夹中inc文文件夹中包含3个文件:stm32f10x.h、stm32f10x_conf.h、stm32f10x_it.h这个三个文件。这3个文件也是官方提供的。如图所示:
STM32 规范工程建立 - ziye334 - ziye334的博客
  BSP的src文件夹张中需要新建一个名为BSP.c的文件,在inc中新建名为BSP.h的文件。
在CMSIS中的src与inc文件中分别包含:core_cm3.c,system_stm32f10x.c和core_cm3.h、system_stm3210x.h。
StartUp文件中存放启动文件,针对不同处理器有对应的启动文件,分别包含:startup_stm32f10x_cl.s、startup_stm32f10x_hd.s、startup_stm32f10x_ld.s、startup_stm32f10x_ld_vl.s、startup_stm32f10x_md.s、startup_stm32f10x_md_vl.s、startup_stm32f10x_xl.s。如下图所示:
STM32 规范工程建立 - ziye334 - ziye334的博客
 这些启动文件的对应的处理器类型如下:
cl:互联型产品,stm32f105/107系列
vl:超值型产品,stm32f100系列
xl:超高密度产品,stm32f101/103系列
ld:低密度产品,FLASH小于64K
md:中等密度产品,FLASH=64 or 128
hd:高密度产品,FLASH大于128
STM32F10x_StdPeriph_Driver文件中的src与inc中分别存放着STM32官方提供的文文件的源文件与头文件,如下图所示:
STM32 规范工程建立 - ziye334 - ziye334的博客STM32 规范工程建立 - ziye334 - ziye334的博客
  3、工程组中添加需要的文件
我们已经建立好了工程的分组,我们按需添加相应的文件,如下图所示:
STM32 规范工程建立 - ziye334 - ziye334的博客
这5个组中CMSIS,StartUp,STM32F10x_StdPeriph_Driver里的文件都是无需修改的文件,从上面图中可以看这些组中的文件都有一个钥匙的标志用来表示它们是只读的。CMSIS组中只要添加core_cm3.c和system_stm32f10x.c两个文件。StartUp组中添加跟处理型号相应的头文件,我的处理器的型号是stm32f103zet6,所以我在工程中添加startup_stm32f10x_hd.s。至于STM32F10x_StdPeriph_Driver这个组要按需添加,上面添加的是通用的,如stm32f10x_flash.c、stm32_gpio.c、stm32f10x_rcc、stm32f10x_usart.c和misc.c,其他可能需要的库文件按功能所需添加。
在应用中,主要修改的就是APP与BSP这两个组的文件。APP需要添加的包括mian.c、stm32f10x_it.c以及stm32f10x_conf.h这几个文件。可能这里大家感到奇怪,怎么讲一个.h文件添加进来了?之所以添加这个stm32f10x_conf.c是因为这个文件代码中包含了所有库文件的头文件,有些可能被注释掉,这要根据库文件的添加而定,正如我们需要保留上面我们STM32F10x_StdPeriph_Driver组中所添加的库文件的头文件,而其他头文件的需要屏蔽掉,如下所示:

//#include "stm32f10x_adc.h"
//#include "stm32f10x_bkp.h"
//#include "stm32f10x_can.h"
//#include "stm32f10x_cec.h"
//#include "stm32f10x_crc.h"
//#include "stm32f10x_dac.h"
//#include "stm32f10x_dbgmcu.h"
//#include "stm32f10x_dma.h"
//#include "stm32f10x_exti.h"
#include "stm32f10x_flash.h"
//#include "stm32f10x_fsmc.h"
#include "stm32f10x_gpio.h"
//#include "stm32f10x_i2c.h"
//#include "stm32f10x_iwdg.h"
//#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
//#include "stm32f10x_rtc.h"
//#include "stm32f10x_sdio.h"
//#include "stm32f10x_spi.h"
//#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"
//#include "stm32f10x_wwdg.h"
#include "misc.h"

4、各文件的代码编写
1)首先是编写的是BSP.c 文件,BSP.c文件需要做很多事情,大多是与开发板驱动相关的。
最先需要初始化系统相关的时钟代码,取名为RCC_Config(),其代码如下:

static void RCC_Config(void)
{
static volatile ErrorStatus HSEStartUpStatus = SUCCESS;

RCC_DeInit(); //默认配置SYSCLK, HCLK, PCLK2, PCLK1, 复位后就是该配置
RCC_HSEConfig(RCC_HSE_ON); //使能外部高速晶振
HSEStartUpStatus = RCC_WaitForHSEStartUp();//等待外部高速稳定

if(HSEStartUpStatus == SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能flash预读取缓冲区
FLASH_SetLatency(FLASH_Latency_2); //令Flash处于等待状态,2是针对高频时钟的
RCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK = SYSCLK 设置高速总线时钟=系统时钟
RCC_PCLK2Config(RCC_HCLK_Div1); //PCLK2 = HCLK 设置低速总线2时钟=高速总线时钟
RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1 = HCLK/2 设置低速总线1的时钟=高速时钟的二分频
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLLCLK = 8MHz * 9 = 72 MHz 利用锁相环讲外部8Mhz晶振9倍频到72Mhz
RCC_PLLCmd(ENABLE); //使能PLL锁相环
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){} //等待锁相环输出稳定
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //将锁相环输出设置为系统时钟
while(RCC_GetSYSCLKSource() != 0x08){} //等待校验成功
}
//使能GPIO口所使用的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOF|RCC_APB2Periph_GPIOG, ENABLE);
}

接下去需要编写一个串口的代码,用于打印程序信息用。我们用串口1最为调试输出接口,波特率可变,代码如下:

static void USART1_Config(u32 baudRate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;

RCC_APB2PeriphClockCmd(COM1_RCC, ENABLE); //使能 USART1 时钟
RCC_APB2PeriphClockCmd(COM1_GPIO_RCC, ENABLE); //使能串口1引脚时钟

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //配置 USART1 的Tx 引脚类型为推挽式的
GPIO_InitStructure.GPIO_Pin = COM1_TX_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(COM1_GPIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//配置 USART1 的Rx 为输入悬空
GPIO_InitStructure.GPIO_Pin = COM1_RX_PIN;
GPIO_Init(COM1_GPIO_PORT, &GPIO_InitStructure);

USART_InitStructure.USART_BaudRate = baudRate;//设置波特率为baudRate
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//设置数据位为8位
USART_InitStructure.USART_StopBits = USART_StopBits_1;//设置停止位为1位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //没有硬件流控
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//发送与接收

USART_ITConfig(COM1, USART_IT_RXNE, ENABLE);//接收中断使能
USART_Init(COM1,&USART_InitStructure); //串口1相关寄存器的配置
USART_Cmd(COM1,ENABLE); //使能串口1
}

为了能够出使用C库函数printf(),还需要添加将printf()重定向到串口接口的相关函数,如下:

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

 

PUTCHAR_PROTOTYPE
{
USART_SendData(USART1, (uint8_t) ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET){}
return ch;
}

如上操作后,在其他文件只要#include 头文件,就可以使用printf()函数打印串口消息了。
为了给其他串口编写提供参考,串口1虽然用于打印消息,我们这里还是开放了串口1的接收中断功能,下面是它的中断设置函数:

static void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //设置中断向量表的基地址为0x08000000
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//设置优先级分组:先占优先级0位,从优先级4位

/*使能USART1中断*/
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //通道设置为串口1中断
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//中断占优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //打开中断
NVIC_Init(&NVIC_InitStructure);
}

我使用的板子上有着4盏LED,在这里我们初始化它们,以便在在调试代码的时候作为指示灯用,代码如下:

static void LED_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(LED1_GPIOX_CLK, ENABLE);//使能LED对应引脚端口的时钟

GPIO_InitStructure.GPIO_Pin = LED1_Pin ; //配置LED1为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LED1_GPIOX, &GPIO_InitStructure);


RCC_APB2PeriphClockCmd(LED2_GPIOX_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = LED2_Pin ; //配置LED2为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LED2_GPIOX, &GPIO_InitStructure);


RCC_APB2PeriphClockCmd(LED2_GPIOX_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = LED3_Pin ; //配置LED3为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LED3_GPIOX, &GPIO_InitStructure);


RCC_APB2PeriphClockCmd(LED4_GPIOX_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = LED4_Pin ; //配置LED1为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LED4_GPIOX, &GPIO_InitStructure);
LED1_OFF();
LED2_OFF();
LED3_OFF();
LED4_OFF();
}

除此之外,还需定义几个定时器函数,分别为微妙级的和毫秒级的。延时函数在调代码中总是要用的,所以在这里留下两个精确定时,代码如下:

void Delay_us(u32 nus)
{
SysTick->LOAD=nus*9; //时间加载
SysTick->CTRL|=0x01; //开始倒数
while(!(SysTick->CTRL&(1<<16)));//等待时间到达
SysTick->CTRL=0X00000000; //关闭计数器
SysTick->VAL=0X00000000; //清空计数器
}

void Delay_ms(u16 nms)
{
SysTick->LOAD=(u32)nms*9000;//给重装载寄存器赋值,9000时,将产生1ms的时基
SysTick->CTRL|=0x01; //开始倒数
while(!(SysTick->CTRL&(1<<16))); //等待时间到达
SysTick->CTRL=0X00000000; //关闭计数器
SysTick->VAL=0X00000000; //清空计数器
}

最后还需要在定义一个总函数:BSP_Init()将必须的初始化函数全部在这个函数内初始化,这样做的话,只要在main()函数调用BSP_Init()就可以了,代码如下:

void BSP_Init(void)
{
RCC_Config();
USART1_Config(115200);
LED_Config();
NVIC_Config();
}

2)BSP.h是配合BSP.c的。
上面的代码,为了移植方便,像引脚都用之类的都用一个宏定义代替,所以还需BSP.h的相关代码,如下:

#ifndef __BSP_H__
#define __BSP_H__
#include "stm32f10x.h"
#include
/*----------printf调试选项----------*/
#define _DEBUG 1
#if _DEBUG
#define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
#else
#define PRINTF(fmt, ...)
#endif
/*----------串口1相关定义----------*/
#define COM1 USART1
#define COM1_RCC RCC_APB2Periph_USART1
#define COM1_GPIO_RCC RCC_APB2Periph_GPIOA
#define COM1_GPIO_PORT GPIOA
#define COM1_TX_PIN GPIO_Pin_9
#define COM1_RX_PIN GPIO_Pin_10
/*----------串口2相关定义----------*/
#define COM2_USART USART2
#define COM2_RCC RCC_APB1Periph_USART2
#define COM2_GPIO_RCC RCC_APB2Periph_GPIOA
#define COM2_GPIO_PORT GPIOA
#define COM2_TX_PIN GPIO_Pin_2
#define COM2_RX_PIN GPIO_Pin_3
/*----------串口3相关定义----------*/
#define COM3 USART3
#define COM3_RCC RCC_APB1Periph_USART3
#define COM3_GPIO_RCC RCC_APB2Periph_GPIOA
#define COM3_GPIO_PORT GPIOB
#define COM3_TX_PIN GPIO_Pin_10
#define COM3_RX_PIN GPIO_Pin_11
/*----------LED1相关定义----------*/
#define LED1_Pin GPIO_Pin_6
#define LED1_GPIOX GPIOF
#define LED1_GPIOX_CLK RCC_APB2Periph_GPIOF
#define LED1_ON() {LED1_GPIOX->BRR = LED1_Pin;}
#define LED1_OFF() {LED1_GPIOX->BSRR = LED1_Pin;}
#define LED1_Toggle() {LED1_GPIOX->ODR = (LED1_GPIOX->ODR)^LED1_Pin;}
/*----------LED2相关定义----------*/
#define LED2_Pin GPIO_Pin_7
#define LED2_GPIOX GPIOF
#define LED2_GPIOX_CLK RCC_APB2Periph_GPIOF
#define LED2_ON() {LED2_GPIOX->BRR = LED2_Pin;}
#define LED2_OFF() {LED2_GPIOX->BSRR = LED2_Pin;}
#define LED2_Toggle() {LED2_GPIOX->ODR = (LED2_GPIOX->ODR)^LED2_Pin;}
/*----------LED3相关定义----------*/
#define LED3_Pin GPIO_Pin_8
#define LED3_GPIOX GPIOF
#define LED3_GPIOX_CLK RCC_APB2Periph_GPIOF
#define LED3_ON() {LED3_GPIOX->BRR = LED3_Pin;}
#define LED3_OFF() {LED3_GPIOX->BSRR = LED3_Pin;}
#define LED3_Toggle() {LED3_GPIOX->ODR = (LED3_GPIOX->ODR)^LED3_Pin;}
/*----------LED4相关定义---------*/
#define LED4_Pin GPIO_Pin_9
#define LED4_GPIOX GPIOF
#define LED4_GPIOX_CLK RCC_APB2Periph_GPIOF
#define LED4_ON() {LED4_GPIOX->BRR = LED4_Pin;}
#define LED4_OFF() {LED4_GPIOX->BSRR = LED4_Pin;}
#define LED4_Toggle() {LED4_GPIOX->ODR = (LED4_GPIOX->ODR)^LED4_Pin;}


void BSP_Init(void);
void Delay_us(u32 nus);
void Delay_ms(u16 nms);
#endif

上面的代码中,我定义了一个宏定义 _DEBUG,根据这个宏定义控制printf()是否输出,如果它为1,使用PRINTF()代替printf()函数,否者定义PRINTF()为空,什么都不执行。这样一来,如果代码成熟后,就可以控制这个定义_DEBUG为0,关闭打印功能以减轻处理器的负担!还为了方便LED灯关闭,分别定义LED灯的亮,灭与亮灭切换的宏定义。
3)stm3210x_it.c文件的编写。
原本来的stm32f10x_it.c可能会包含全部中断的中断服务程序,如果中断没有定义,那么这些中断服务程序我觉的就是多余的了,所以我就将他们全删掉了,只留下需要的。正如我这个工程,我之前只定义了串口中断,所以要将串口的中断服务程序保留,为了防止出现硬件错误,我还保留了硬件错误的中断服务程序,代码如下:

#include "stm32f10x_it.h"
#include

 

void HardFault_Handler(void)
{
printf("Hard error!!!\r\n");
NVIC_SystemReset(); //软件复位
}

void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
USART_SendData(USART1,USART_ReceiveData(USART1));//发送收到的字节
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);//等待发送完成
}
}

上面代码中,为了防止硬件出现错误,我们在硬件中断服务程序中,用printf()给出提示硬件错误信息,并且出现错误时调用NVIC_SystemReset()软件复位。在串口中断服务程序中,将接收的数据如数返回。
4)main.c函数的编写
  main.c的代码就很简单了,不展开讲了,直接贴代码:

#include "stm32f10x.h"
#include "BSP.h"

int main(void)
{
BSP_Init();
PRINTF("\nmain() is running!\r\n");
while(1)
{
LED1_Toggle();
Delay_ms(1000);
}
}

 
5、工程的拓展
怎么在这个工程上拓展呢?前面也说过,文件的添加主要要添加到APP与BSP两个组中。BSP主要放类似驱动的文件,而APP怎放应用程序。举个例子说,我要控制舵机,舵机需要PWM波控制,所以需要编写PWM相关的驱动文件,比如我们取名为:Driver.c,在这个文件里编写PWM的程序,能够让舵机转动就可以了,然后将Driver.c添加到BSP组中。接下去,我们还需要编写舵机控制程序,比如说舵机怎么转,转多少角度,或者直接编写一个舵机转动动作,我们取名为Control.c,这个文件则需要添加到APP组中。
最后需要说明是,工程中的注释其实也是有讲究的,由于限于篇幅以及博客的显示效果,这里没有将注释规范部分全部给出。
关键字:STM32  规范工程建立 引用地址:STM32 规范工程建立

上一篇:STM32 IO口模拟串口通讯
下一篇:STM32 SHT10温湿度传感器的信号采集

推荐阅读最新更新时间:2024-03-16 15:14

STM32 串口烧写 FLASH 外部字库 UCGUI显示 自我学习总结
最近学习TFT显示问题,在多种汉字显示方面有点难,主要是字库太大,几个字库就不得了。开始是使用SD卡向外部FLASH---W25X16写,完全能够完成。后来觉得这样比较麻烦,有时候还没有SD接口,于是打算用串口写一下试一试,网上有很多人说会丢失数据,在后面的试验中暂时没有发现。 我是在我前段时间学习的UCGUI的基础基础上修改的。 主要功能是----启动开发板,首先写入地址指令----必须十六进制----比如---2A 23 00 05 00 03 23 2A-----其中2A,23为验证码,前后都有,第3,4位是地址码,前面就表示将要写入的起始地址是0x05*4096,第5,6位是为了写入数据将要
[单片机]
<font color='red'>STM32</font> 串口烧写 FLASH 外部字库 UCGUI显示 自我学习总结
意法半导体stm32系列芯片的省电原因
stm32所有寄存器都需要时钟才能配置,寄存器是由D触发器组成的,只有送来了时钟,触发器才能被改写值。 任何MCU的任何外设都需要有时钟,8051也是如此;STM32为了让用户更好地掌握功耗,对每个外设的时钟都设置了开关,让用户可以精确地控制,关闭不需要的设备,达到节省供电的目的。 51单片机不用配置IO时钟,只是因为默认使用同一个时钟,这样是方便,但是这样的话功耗就降低不了。 例如,某个功能不需要,但是它还是一直运行。 STM32需要配置时钟,就可以把不需要那些功能的功耗去掉。 当你想关闭某个IO的时候,关闭它想对应的时钟使能就是了,不过在51里面,在使用IO的时候是没有设置IO的时钟的,还有在STM32中,
[嵌入式]
关于STM32串口接收中断中只能接收一个字节
最近调试STM32的串口接收时发现例程中只能接收一个字节 例程如下: 1 //初始化串口1 2 void uart_init(u32 bound){ 3 //GPIO端口设置 4 GPIO_InitTypeDef GPIO_InitStructure; 5 USART_InitTypeDef USART_InitStructure; 6 NVIC_InitTypeDef NVIC_InitStructure; 7 8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USA
[单片机]
STM32的看门狗使用方法
简介:stm32自带两个看门狗模块,独立看门狗IWDG和窗口看门狗WWDG。主要作用是——可用来检测和解决由软件错误引起的故障;当计数器达到给定的超时值时,触发一个中断(仅适用于窗口型看门狗)或产生系统复位。 具体的实现步骤:开启看门狗,设置减计数的初始值,当计数值达到超时值时,产生MCU复位,此时本来运行的程序终止重新启动单片机(发生了故障)。在使用了看门狗之后,在正常运行的程序中加入喂狗的程序,即采用定时器的方式每隔一段时间进行一次喂狗重置计数装载值,这样,只要程序正常运行,没有出现故障或软件错误,就会不断的定时喂狗,从而不会使计数值达到超时值产生复位。 独立看门狗IWDG: IWDG主要性能 ●自由运行的递减
[单片机]
stm32定时器输入捕获pwm
花了两天时间终于把stm32f103的定时器输入捕获弄懂了,这里以TIM3的通道ch1为例,要实现输入捕获需要配置一下寄存器,TIMx_ARR,TIMx_PSC,TIMx_CCMR1,TIMx_CCER,TIMx_DIER,TIMx_CR1,TIMx_CCR1.这里抓取了一些收据手册中寄存器描述的图 下面一一介绍: TIMx_ARR寄存器为自动重装载的值 TIMx_CR1这里了只要用到它的第0位即使能位。 TIMx_CCMR可以配置对应通道映射到那个IC,TI。 这里我们是第一通道故只需配置低8位,cc1s为配置ch1映射到那个TI,IC1PSC为配置是否分频,1c1f为配置是否滤波。 TIMx_psc寄存器 T
[单片机]
STM32STM32系统架构浅析
在学习STM32芯片的强大外设功能之前,首先要从宏观上学习芯片的系统架构,明白各个模块之间的层级关系以及相互的影响。只有从宏观上把握了,才不至于“掉入细节之中,不识庐山真面目”。 本文从整体构架上构建宏观的概念以及联系,不会太深入剖析具体实现原理。 1 系统架构图 上面的架构图主要包含: ARM公司提供的内核:cortex-M3 ARM公司提供的总线:Icode,Dcode,System总线 ST公司提供的总线矩阵,DMA控制器,AHB总线,APB总线,以及各个外设控制器 以上整体称之为片上系统(SOC),每个模块各司其职,存在竞争与合作。 2 计算机组成原理 计算机组成原理告诉我们,计算机硬件由5大部分构成:运算
[单片机]
【<font color='red'>STM32</font>】<font color='red'>STM32</font>系统架构浅析
STM32】SRAM启动
创建工程的调试版本 该操作调试版本会复制原工程的配置 修改FLASH的目标配置 用的是STM32F103C8T6 RAM起始地址为是0x2000 0000大小为20KB, 这里用12KB大小的RAM作为虚拟ROM,用8KB的RAM作为RAM 虚拟ROM起始地址0x2000 0000大小0x3000 RAM起始地址0x2000 3000大小0x2000 配置分散加载文件 keil STM32中sct 分散加载文件学习 注意要与FLASH下的目标配置一致 虚拟ROM起始地址0x2000 0000大小0x3000 RAM起始地址0x2000 3000大小0x2000 ; *************************
[单片机]
【<font color='red'>STM32</font>】SRAM启动
基于STM32单片机的电子称设计
摘要 电子秤是将检测与转换技术、计算机技术、信息处理、数字技术等技术综合一体的现代新型称重仪器。它与我们日常生活紧密结合息息相关。 电子称主要以单片机作为中心控制单元,通过称重传感器进行模数转换单元,在配以键盘、显示电路及强大软件来组成。电子称不但计量准确、快速方便,更重要的自动称重、数字显示,对人们生活的影响越来越大,广受欢迎。 本系统的设计主要从硬件电路设计,软件编程调试,实物焊接调试三部分进行详细阐述。硬件电路主要是基于单片机为核心的控制单元实现数据的处理,采用压力传感器对数据进行采集,电子秤专用24位AD转换芯片HX711对传感器采集到的模拟量进行AD转换,转换后的数据送到单片机进行处理显示,数据显示由LCD160
[单片机]
基于<font color='red'>STM32</font>单片机的电子称设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved