完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
库函数版 led.h #ifndef __LED_H #define __LED_H void LED_Init(void); //初始化 #endif led.c #include "led.h" void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5 GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出 GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高 } 主函数main #include "stm32f10x.h" #include "led.h" #include "delay.h" //注意:此延时函数位正点原子自带延时函数 int main(void) { delay_init(); //初始化延时函数 LED_Init(); //初始化LED端口 while(1) { GPIO_ResetBits(GPIOB,GPIO_Pin_5); //LED0对应引脚GPIOB.5拉低,亮 等同LED0=0; GPIO_SetBits(GPIOE,GPIO_Pin_5); //LED1对应引脚GPIOE.5拉高,灭 等同LED1=1; delay_ms(300); //延时300ms GPIO_SetBits(GPIOB,GPIO_Pin_5); //LED0对应引脚GPIOB.5拉高,灭 等同LED0=1; GPIO_ResetBits(GPIOE,GPIO_Pin_5); //LED1对应引脚GPIOE.5拉低,亮 等同LED1=0; delay_ms(300); //延时300ms } } 寄存器版 led.h #ifndef __LED_H #define __LED_H void LED_Init(void); //初始化 #endif 步骤一:先对APB2外设时钟使能寄存器(RCC_APB2ENR)第3位(端口B)和第6位(端口E)操作 方法:( |= 例: A |= B 为 A = A | B ) 步骤二:对端口配置低寄存器(GPIOx_CRL) (x=A…E) 第5位进行操作(清零并且设置模式) 方法:先配置模式,因为推挽输出并设置速度50MHz,第19、18、17、16位为0011,换成16进制为0x00300000 步骤三:端口输出数据寄存器(GPIOx_ODR) (x=A…E) led.c文件 void LED_Init(void) { RCC->APB2ENR|=1<<3; //使能PORTB时钟 RCC->APB2ENR|=1<<6; //使能PORTE时钟 GPIOB->CRL&=0XFF0FFFFF; //对寄存器清零 GPIOB->CRL|=0X00300000;//PB.5 推挽输出 GPIOB->ODR|=1<<5; //PB.5 输出高 GPIOE->CRL&=0XFF0FFFFF; GPIOE->CRL|=0X00300000;//PE.5推挽输出 GPIOE->ODR|=1<<5; //PE.5输出高 } 主函数main #include "stm32f10x.h" #include "delay.h" //注意:此延时函数位正点原子自带延时函数 #include "led.h" int main(vodi) { delay_init(); LED_Init(); while(1) { GPIOB->ODR |=1<<5; //设置高电平LED位灭 GPIOE->ODR |=1<<5; delay_ms(500); //延时500 GPIOE->ODR =~1<<5; //非运算取反为低电平点亮LED GPIOE->ODR =~1<<5; delay_ms(500); } } 位带操作 主函数main int main(void) delay_init(); LED_Init(); while(1) { PBout(5)=1; //PBout和PEout在 Sys.h头文件已经定义 PEout(5)=1; delay_ms(500); PBout(5)=1; PEout(5)=1; delay_ms(500); } 附录 sys.h #ifndef __SYS_H #define __SYS_H #include "stm32f10x.h" //0,不支持ucos //1,支持ucos #define SYSTEM_SUPPORT_OS 0 //定义系统文件夹是否支持UCOS //位带操作,实现51类似的GPIO控制功能 //具体实现思想,参考< //IO口操作宏定义 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) //IO口地址映射 #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08 //IO口操作,只对单一的IO口! //确保n的值小于16! #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出 #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出 #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出 #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出 #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出 #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出 #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出 #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入 //以下为汇编函数 void WFI_SET(void); //执行WFI指令 void INTX_DISABLE(void);//关闭所有中断 void INTX_ENABLE(void); //开启所有中断 void MSR_MSP(u32 addr); //设置堆栈地址 #endif sys.c #include "sys.h" //THUMB指令不支持汇编内联 //采用如下方法实现执行汇编指令WFI void WFI_SET(void) { __ASM volatile("wfi"); } //关闭所有中断 void INTX_DISABLE(void) { __ASM volatile("cpsid i"); } //开启所有中断 void INTX_ENABLE(void) { __ASM volatile("cpsie i"); } //设置栈顶地址 //addr:栈顶地址 __asm void MSR_MSP(u32 addr) { MSR MSP, r0 //set Main Stack value BX r14 } delay.h #ifndef __DELAY_H #define __DELAY_H #include "sys.h" void delay_init(void); void delay_ms(u16 nms); void delay_us(u32 nus); #endif delay.c #include "delay.h" // //如果需要使用OS,则包括下面的头文件即可. #if SYSTEM_SUPPORT_OS #include "includes.h" //ucos 使用 #endif static u8 fac_us=0; //us延时倍乘数 static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数 #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS定义了,说明要支持OS了(不限于UCOS). //当delay_us/delay_ms需要支持OS的时候需要三个与OS相关的宏定义和函数来支持 //首先是3个宏定义: // delay_osrunning:用于表示OS当前是否正在运行,以决定是否可以使用相关函数 //delay_ostickspersec:用于表示OS设定的时钟节拍,delay_init将根据这个参数来初始哈systick // delay_osintnesting:用于表示OS中断嵌套级别,因为中断里面不可以调度,delay_ms使用该参数来决定如何运行 //然后是3个函数: // delay_osschedlock:用于锁定OS任务调度,禁止调度 //delay_osschedunlock:用于解锁OS任务调度,重新开启调度 // delay_ostimedly:用于OS延时,可以引起任务调度. //本例程仅作UCOSII和UCOSIII的支持,其他OS,请自行参考着移植 //支持UCOSII #ifdef OS_CRITICAL_METHOD //OS_CRITICAL_METHOD定义了,说明要支持UCOSII #define delay_osrunning OSRunning //OS是否运行标记,0,不运行;1,在运行 #define delay_ostickspersec OS_TICKS_PER_SEC //OS时钟节拍,即每秒调度次数 #define delay_osintnesting OSIntNesting //中断嵌套级别,即中断嵌套次数 #endif //支持UCOSIII #ifdef CPU_CFG_CRITICAL_METHOD //CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII #define delay_osrunning OSRunning //OS是否运行标记,0,不运行;1,在运行 #define delay_ostickspersec OSCfg_TickRate_Hz //OS时钟节拍,即每秒调度次数 #define delay_osintnesting OSIntNestingCtr //中断嵌套级别,即中断嵌套次数 #endif //us级延时时,关闭任务调度(防止打断us级延迟) void delay_osschedlock(void) { #ifdef CPU_CFG_CRITICAL_METHOD //使用UCOSIII OS_ERR err; OSSchedLock(&err); //UCOSIII的方式,禁止调度,防止打断us延时 #else //否则UCOSII OSSchedLock(); //UCOSII的方式,禁止调度,防止打断us延时 #endif } //us级延时时,恢复任务调度 void delay_osschedunlock(void) { #ifdef CPU_CFG_CRITICAL_METHOD //使用UCOSIII OS_ERR err; OSSchedUnlock(&err); //UCOSIII的方式,恢复调度 #else //否则UCOSII OSSchedUnlock(); //UCOSII的方式,恢复调度 #endif } //调用OS自带的延时函数延时 //ticks:延时的节拍数 void delay_ostimedly(u32 ticks) { #ifdef CPU_CFG_CRITICAL_METHOD OS_ERR err; OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err); //UCOSIII延时采用周期模式 #else OSTimeDly(ticks); //UCOSII延时 #endif } //systick中断服务函数,使用ucos时用到 void SysTick_Handler(void) { if(delay_osrunning==1) //OS开始跑了,才执行正常的调度处理 { OSIntEnter(); //进入中断 OSTimeTick(); //调用ucos的时钟服务程序 OSIntExit(); //触发任务切换软中断 } } #endif //初始化延迟函数 //当使用OS的时候,此函数会初始化OS的时钟节拍 //SYSTICK的时钟固定为HCLK时钟的1/8 //SYSCLK:系统时钟 void delay_init() { #if SYSTEM_SUPPORT_OS //如果需要支持OS. u32 reload; #endif SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8 fac_us=SystemCoreClock/8000000; //为系统时钟的1/8 #if SYSTEM_SUPPORT_OS //如果需要支持OS. reload=SystemCoreClock/8000000; //每秒钟的计数次数 单位为M reload*=1000000/delay_ostickspersec; //根据delay_ostickspersec设定溢出时间 //reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右 fac_ms=1000/delay_ostickspersec; //代表OS可以延时的最少单位 SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断 SysTick->LOAD=reload; //每1/delay_ostickspersec秒中断一次 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK #else fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数 #endif } #if SYSTEM_SUPPORT_OS //如果需要支持OS. //延时nus //nus为要延时的us数. void delay_us(u32 nus) { u32 ticks; u32 told,tnow,tcnt=0; u32 reload=SysTick->LOAD; //LOAD的值 ticks=nus*fac_us; //需要的节拍数 tcnt=0; delay_osschedlock(); //阻止OS调度,防止打断us延时 told=SysTick->VAL; //刚进入时的计数器值 while(1) { tnow=SysTick->VAL; if(tnow!=told) { if(tnow told=tnow; if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出. } }; delay_osschedunlock(); //恢复OS调度 } //延时nms //nms:要延时的ms数 void delay_ms(u16 nms) { if(delay_osrunning&&delay_osintnesting==0) //如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度) { if(nms>=fac_ms) //延时的时间大于OS的最少时间周期 { delay_ostimedly(nms/fac_ms); //OS延时 } nms%=fac_ms; //OS已经无法提供这么小的延时了,采用普通方式延时 } delay_us((u32)(nms*1000)); //普通方式延时 } #else //不用OS时 //延时nus //nus为要延时的us数. void delay_us(u32 nus) { u32 temp; SysTick->LOAD=nus*fac_us; //时间加载 SysTick->VAL=0x00; //清空计数器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } //延时nms //注意nms的范围 //SysTick->LOAD为24位寄存器,所以,最大延时为: //nms<=0xffffff*8*1000/SYSCLK //SYSCLK单位为Hz,nms单位为ms //对72M条件下,nms<=1864 void delay_ms(u16 nms) { u32 temp; SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit) SysTick->VAL =0x00; //清空计数器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } #endif |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1649 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1566 浏览 1 评论
994 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
694 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1613 浏览 2 评论
1872浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
659浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
527浏览 3评论
544浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
516浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-28 06:21 , Processed in 0.618527 second(s), Total 73, Slave 57 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号