历史上的今天
返回首页

历史上的今天

今天是:2025年03月09日(星期日)

正在发生

2019年03月09日 | 使用STM32固件库函数操作控制LED灯

2019-03-09 来源:eefocus

       直接使用寄存器地址来进行STM32开发要对每一个寄存器的地址通过查找芯片手册,对每一个寄存器的各个位的含义也要查清楚,然后决定对那个地址的哪些位进行怎样的设置。这种编程效率低,程序的可移植性差,程序的可读性差。


       STM32提供了对外设寄存器操作的功能函数,对寄存器操作只需要调用相应的库函数就可以,一般函数名单词组合与功能密切相关,增强了程序的可读性。


1、以CMSIS固件库项目为基础,在项目文件夹下新增"Lib"文件夹,在"Lib"文件夹下新增"inc"和"src"文件夹,在"inc"文件夹中复制"stm32f10x_gpio.h"和"stm32f10x_rcc.h"两个头文件,在"src"文件夹中复制"stm32f10x_gpio.c"和"stm32f10x_rcc.c"两个库函数程序文件,分别包含RCC和GPIO操作相关的库函数。


2、在“项目条目管理”对话框中添加"Lib"组,并向组中添加两个库函数程序文件。



3、修改"Include Paths",添加".\Lib\inc"路径



4、重写main.c中的main函数


① 包含需要的头文件:"stm32f10x_gpio.h"和"stm32f10x_rcc.h"


② 使能GPIOC时钟


    在RCC库函数中定义了RCC_APB2PeriphClockCmd函数,函数原型为:


void RCC_APB2PeriphClockCmd ( uint32_t  RCC_APB2Periph, FunctionalState  NewState )


其中参数RCC_APB2Periph取值为在"stm32f10x_rcc.h"中预定义的值,这里对GPIOC的操作为RCC_APB2Periph_GPIOC,定义如下:



这个值与前面程序中的表达式"0x1<<4"得到的值是一致的。


    函数的第二个参数NewState取值为FunctionState类型,FunctionState类型是在"stm32f10x_rcc.c"文件中定义的一个枚举类型,有DISABLE和ENABLE两个取值,定义如下:



    现在要使能GPIOC,则调用函数如下:


RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );


③ 配置GPIOC_0为推挽式输出,50MHz速度。


    对GPIO引脚的配置调用"stm32f10x_gpio.c"中的库函数GPIO_Init实现,函数原型为:


void GPIO_Init ( GPIO_TypeDef *  GPIOx, GPIO_InitTypeDef * GPIO_InitStruct  )


其中第一个参数GPIOx的取值在"stm32f10x.h"中定义,这里用GPIOC;第二个参数GPIO_InitStruct为GPIO_InitTypeDef指针类型,GPIO_InitTypeDef类型在"stm32f10x_gpio.h"文件中定义:



这个结构体中的GPIO_Pin为IO口的引脚编号,这里为第一个LED灯,则取0;


GPIO_Speed为GPIOSpeed_TypeDef类型,GPIOSpeed_TypeDef类型在"stm32f10x_gpio.h"文件中定义:



为枚举类型,有三个枚举值。这里取GPIO_Speed_50MHz;


GPIO_Mode为GPIOMode_TypeDef类型,GPIOMode_TypeDef类型在"stm32f10x_gpio.h"文件中定义:

    这些枚举值分别为:


(1)GPIO_Mode_AIN 模拟输入


(2)GPIO_Mode_IN_FLOATING 浮空输入


(3)GPIO_Mode_IPD 下拉输入


(4)GPIO_Mode_IPU 上拉输入


(5)GPIO_Mode_Out_OD 开漏输出


(6)GPIO_Mode_Out_PP 推挽输出


(7)GPIO_Mode_AF_OD 复用开漏输出


(8)GPIO_Mode_AF_PP 复用推挽输出


    这里选择GPIO_Mode_Out_PP。


要配置GPIOC_0的工作模式,首先用GPIO_InitTypeDef类型定义一个变量,然后给这个结构体变量的成员赋值,最后调用GPIO_Init函数完成配置:


GPIO_InitTypeDef GPIOC_0_mode;


GPIOC_0_mode.GPIO_Pin = GPIO_Pin_0;


GPIOC_0_mode.GPIO_Speed = GPIO_Speed_50MHz;


GPIOC_0_mode.GPIO_Mode = GPIO_Mode_Out_PP;


GPIO_Init(GPIOC, &GPIOC_0_mode);


④ 通过GPIO_ResetBits和GPIO_SetBits函数来控制LED1的复位和置位,函数原型如下:


void GPIO_ResetBits ( GPIO_TypeDef *GPIOx,  uint16_t  GPIO_Pin )       //复位函数


void GPIO_SetBits  ( GPIO_TypeDef * GPIOx,  uint16_t GPIO_Pin ) //置位函数


函数的参数分别为哪个GPIO口和哪个引脚。


如果对GPIOC_0复位,则:GPIO_ResetBits( GPIOC, GPIO_Pin_0) ;


如果对GPIOC_0置位,则:GPIO_SetBits( GPIOC, GPIO_Pin_0) ;


最后的main.c程序如下:


#include "stm32f10x.h"


#include "stm32f10x_rcc.h"


#include "stm32f10x_gpio.h"


void delay(int t)


{


     int i;


     for( ;t>0; t--)


         for(i=0;i<1000;i++);


}


int main()


{


     GPIO_InitTypeDef GPIOC_0_mode;


     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE ); //使能GPIOC时钟


     GPIOC_0_mode.GPIO_Pin = GPIO_Pin_0;


     GPIOC_0_mode.GPIO_Speed = GPIO_Speed_50MHz;


     GPIOC_0_mode.GPIO_Mode = GPIO_Mode_Out_PP;


     GPIO_Init(GPIOC, &GPIOC_0_mode);   //配置GPIOC_0引脚为推挽输出,50MHz速度


     while(1)


     {


         GPIO_ResetBits( GPIOC, GPIO_Pin_0);  //将GPIOC_0复位


         delay(1000);


         GPIO_SetBits( GPIOC, GPIO_Pin_0);    //将GPIOC_0置位


         delay(1000);


     }


}


5、连接错误及其解决方法。


在上述项目中,最后完成项目配置和编程后,编译连接时出现如下错误:


出现这个错误是由于STM32外设库函数的开发中用到了断言机制。正常使用库函数时,需要包含"stm32f10x_conf.h"头文件,在该文件中有如下定义


/* Exported macro ------------------------------------------------------------*/


#ifdef  USE_FULL_ASSERT


/**


  * @brief  The assert_param macro is used for function's parameters check.


  * @param  expr: If expr is false, it calls assert_failed function which reports


  *         the name of the source file and the source line number of the call


  *         that failed. If expr is true, it returns no value.


  * @retval None


  */


  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))


/* Exported functions ------------------------------------------------------- */


  void assert_failed(uint8_t* file, uint32_t line);


#else


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


#endif /* USE_FULL_ASSERT */


在该头文件中定义了assert_param宏,根据项目配置,如果设置了"USE_FULL_ASSERT"参数,则对函数参数进行检查,检查不成功转到"assert_failed"函数处理;如果没有设置使用断言,则相当于不对参数进行检测。


解决方法:将这一段宏定义直接复制到"stm32f10x.h"文件中,因为所有的外设库函数文件都直接或间接地包含了该头文件。


6、编译连接项目,下载程序,开发板的LED1闪烁。


推荐阅读

史海拾趣

FRONTIER公司的发展小趣事

背景:FRONTIER Electronics作为一家专注于无源元件和集成无源元件设计与制造的公司,自成立以来便致力于技术创新。

发展故事:在21世纪初,FRONTIER Electronics凭借其在电感器、变压器、二极管等领域的深厚技术积累,成功推出了一系列高性能、高可靠性的电子产品。随着市场需求的不断增长,公司逐步扩大生产规模,并在全球范围内建立了完善的销售网络。通过持续的技术研发和市场拓展,FRONTIER Electronics逐渐在电子行业中崭露头角,成为该领域的领军企业之一。

Harwin公司的发展小趣事

Harbour Industries成立于1965年,起初主要专注于电缆的生产与销售。在20世纪60年代末和70年代初期,随着全球航空航天市场的迅速增长,Harbour敏锐地捕捉到了这一机遇。为了服务这一市场,公司进行了大规模的工厂扩建,并引入了先进的生产设备和技术。这一举措不仅提升了公司的产能,还确保了产品质量能够满足航空领域的高标准。通过不懈努力,Harbour逐渐在航空电缆市场中占据了一席之地。

BB公司的发展小趣事

2000年,BB公司迎来了发展史上的一个重要时刻——被美国德州仪器公司收购。这一收购对于BB公司来说,既是挑战也是机遇。德州仪器作为全球领先的半导体公司,为BB公司提供了更广阔的平台和更丰富的资源。在德州仪器的支持下,BB公司得以继续深化技术创新和市场拓展,进一步提升了其在电子行业的地位。

ADMOS公司的发展小趣事

在电子行业的早期,ADMOS公司以其前瞻性的技术视野和不懈的研发努力,成功开发出一款高效能、低能耗的功率管理芯片。这款芯片在市场上迅速获得了认可,为ADMOS公司赢得了良好的口碑。这一技术突破不仅奠定了ADMOS在功率管理领域的领先地位,也为公司的后续发展奠定了坚实的基础。

CMOSIS公司的发展小趣事

在CMOS图像传感器市场竞争日益激烈的背景下,CMOSIS公司凭借其深厚的技术积累,成功研发出一款新型CMOS图像传感器,具有更高的分辨率和更低的噪声水平。这一技术突破使得CMOSIS的产品在市场上脱颖而出,赢得了众多客户的青睐。公司通过不断优化生产工艺和降低成本,逐渐扩大了市场份额,成为行业内的佼佼者。

Crane Connectors公司的发展小趣事

Crane Connectors公司深知产品质量是企业生存和发展的根本。因此,公司始终将质量管理放在首位,建立了完善的质量管理体系。从原材料采购、生产加工到产品检验、售后服务,每一个环节都严格把控,确保产品质量符合国际标准和客户要求。同时,公司还不断引进先进的质量管理理念和技术手段,提升质量管理水平。这些举措使得公司的产品质量得到了客户的高度认可,进一步提升了公司的市场竞争力。

问答坊 | AI 解惑

意外的惊喜!考研+就业!

考研就业专刊 考研流程+考研经验+人才招聘会+薪资洽谈+面试攻略+健康贴士+时间表…… 妹妹大餐都在这里面! 尤其适合自动化相关专业,特别版!一路陪伴从准备到结束!!! 为了节省大家的芯币 本人最新编辑了一下 把所有的东西打 ...…

查看全部问答>

request_dma()函数中第一个参数是怎么得到?

int request_dma(unsigned int dmanr, const char * device_id) 参数dmanr是从0~3、5~7里面的随便挑一个就行了么? 还是需要怎么做来得到啊…

查看全部问答>

大家给我出出主意

几个问题 1.嵌入式的前景不错嘛?酬薪怎样? 2.嵌入式工程师没有35岁瓶颈吗? 3.我是个学生,想问下培训费用大概多少钱? 4.对于现在的情况,大学生是不是很需要培训,培训的目的和作用是什么? 我是个新手,希望大家好好指导我下。谢谢。大二 ...…

查看全部问答>

ARM7中断疑惑?请哪个大虾帮忙看看。小弟不胜感激!

在ARM7下写了一个定时器中断程序。下面代码是进入IRQ中断后然后为了可重入中断,就切换到系统模式下。但是在切换的时候出现问题?如何直接MSR CPSR_C,#SYS32_MODE(1)就出现SIGBUS错误。切换代码改成MSR CPSR_C,#(SYS32_MODE|NO_INT)(2)就行了 ...…

查看全部问答>

Tornado2.2(arm)的USB2.0问题

我的Tornado2.2里为什么没有EHCI和EHCI Init组件 但是别人好像有这个组件啊,是不是序列号的问题? 而且,我在pudn上下了安装,貌似就是t22-cp1-arm.tar那个东西,但是里面还是没有啊?请问高手怎么回事情啊? http://www.pudn.com/downloads148 ...…

查看全部问答>

uCOS-II内部机制

附件中的文件非常简洁的讲述了uCOS-II的内部机制,是不错的学习OS的资料…

查看全部问答>

EZ430——Rf2500学习小感

最近刚刚入手430,原来只接触过51,不过由于430的程序大都用C写得,所以学习起来还是比较方便的。前几天一直在学习uart的输出,具体做了一个有关uart的小程序,刚开始有例程可以看,不过不知道问什么,所有的例程都无法用串口助手加以显示输出,当 ...…

查看全部问答>

中断嵌套学习一些心得

中断嵌套,优先级430总中断的控制位是状态寄存器内的GIE位(该位在SR寄存器内),该位在复位状态下,所有的可屏蔽中断都不会发生响应。可屏蔽中断又分为单中断源和多中断源的。单中断源的一般响应了中断服务程序中断标志位就自动清零,而多中断源的 ...…

查看全部问答>

求助:可以给单片机外接晶体振荡器求出该晶振频率吗?

已知一个石英晶体的谐振频率为5MHz左右(大概偏差几十Hz),想要较为准确测试出其谐振频率,可以把它作为一个晶振,接到单片机的两个晶振输入端,然后算出这个石英晶体的谐振频率么?如果可以的话,具体怎么接怎么求算?精度如何?对应的程序怎么写 ...…

查看全部问答>

CCS controlSUITE是干什么用的?

(DSP)管网上说这个是C2000系列的例程,帮助,等文件软件,反正就是学习C2000安装这个肯定有用,不知道学习C5000,安装这个有没有用???…

查看全部问答>