1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
一、STM32F103C8T6简介
STM32F103C8T6是一款由意法半导体公司(ST)推出的基于Cortex-M3内核的32位微控制器,硬件采用LQFP48封装,属于ST公司微控制器中的STM32系列。 二、初始化GPIO,点亮LED灯 外设的功能都是完全不同的,但初始化都是大同小异的。 点灯是所有学单片机的人都应该学会的第一项技能,这样子才算入门。 51单片机的点灯是,通过控制寄存器将片外引脚(我们称之为IO口)拉低拉高,输出高低电平,以控制LED亮灭。 其过程:单片机给指令->控制寄存器->给IO口电平->控制LED亮灭 stm32的点灯则是,通过使能外设GPIO时钟,发出指令给外设GPIO,外设GPIO收到指令后,着手配置自己的寄存器,然后给IO口模式,让其实现各种功能。 其过程:CPU给指令->GPIO收到指令->配置内部寄存器->配置IO口模式(注意是模式)->控制LED亮灭。 三、以 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED 搭建电路,使用GPIOB、GPIOC、GPIOD这3个端口控制LED灯(最高时钟2Mhz),轮流闪烁,间隔时长1秒。 在正点原子openedv资料下载地址下载mini板的rct6资料,开发板的例程。 (一)建立工程模板 1.创建项目 2.选择芯片 3.添加项目所需要的分组以及文件 4.创建Groups名字,点击右边的Add Files…按钮添加相应的文件 5.配置Options for Target 'Target 1’ 点击Target,可以看到STM芯片为STM32F103C8,修改晶振频率值为8 点击Output,其中select folder for objects是选择生成的hex存放的目录,这里选择存放在建立的OBJ文件夹中,Create HEX File用于生成可执行代码文件(可以用编程器写入单片机芯片的 HEX 格式文件,文件的扩展名为.HEX) 接着点击C/C++选项,将其中的Define设置为USE_STDPERIPH_DRIVER,STM32F10X_MD,然后点击右下方的添加按钮添加Include Paths的路径 (二)配置GPIO端口 GPIO端口的初始化设置三步骤: 时钟配置 输入输出模式设置 最大速率设置 1.配置时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启 GPIOB 端口时钟 2.初始化结构体 // @file stm32f10x_gpio.h typedef struct { uint16_t GPIO_Pin; /*!< 选择要配置的 GPIO 引脚 */ GPIOSpeed_TypeDef GPIO_Speed; /*!< 选择 GPIO 引脚的速率 */ GPIOMode_TypeDef GPIO_Mode; /*!< 选择 GPIO 引脚的工作模式 */ }GPIO_InitTypeDef; 3.配置输入输出模式 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //输出模式为通用推挽输出 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4 ; //选定输出端口为GPIO_Pin_4 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz; //输出速度为2M GPIO_Init(GPIOA,&GPIO_InitStruct); (三)主要函数 1.led.h #ifndef _LED_H #define _LED_H #include "stm32f10x.h" void LED_R_TOGGLE(void); void LED_G_TOGGLE(void); void LED_Y_TOGGLE(void); void LED_Init(void); #endif 2.led.c #include "led.h" #include "delay.h" void LED_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE); //打开外设GPIOB的时钟 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //输出模式为通用推挽输出 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4 ; //选定端口为GPIO_Pin_4 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz; //输出速度为2M GPIO_Init(GPIOA,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //输出模式为通用推挽输出 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10 ; //选定端口为GPIO_Pin_1 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz; //输出速度为2M GPIO_Init(GPIOB,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //输出模式为通用推挽输出 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_14 ; //选定端口为GPIO_Pin_14 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz; //输出速度为2M GPIO_Init(GPIOC,&GPIO_InitStruct); } void LED_R_TOGGLE(void) { GPIO_SetBits(GPIOA, GPIO_Pin_4); delay_ms(500); GPIO_ResetBits(GPIOA,GPIO_Pin_4); } void LED_G_TOGGLE(void) { GPIO_SetBits(GPIOB, GPIO_Pin_10); delay_ms(500); GPIO_ResetBits(GPIOB,GPIO_Pin_10); } void LED_Y_TOGGLE(void) { GPIO_SetBits(GPIOC, GPIO_Pin_14); delay_ms(500); GPIO_ResetBits(GPIOC,GPIO_Pin_14); } 3.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 4.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). #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 5.main.c #include "stm32f10x.h" #include "delay.h" #include "led.h" int main(void) { LED_Init(); delay_init(); //使用系统滴答定时器、延时初始化 while(1) //循环亮起 { LED_R_TOGGLE(); delay_ms(500); //红灯亮后延时1s LED_G_TOGGLE(); delay_ms(500); //绿灯亮后延时1s LED_Y_TOGGLE(); delay_ms(500); //黄灯亮后延时1s } } 6.生成.HEX文件 (四)搭建电路 GND — GND 3v3 — 3v3 TXD — A10 RXD — A9 1.用串口下载程序 要使用串口得先在电脑中安装 USB 转串口驱动—CH340 版本 2.打开 mcuisp 软件,配置如下: ①搜索串口,设置波特率 115200(尽量不要设置的太高) ②选择要下载的HEX 文件 ③校验、编程后执行 ④DTR 低电平复位,RTS 高电平进入 bootloader ⑤开始编程,如果出现一直连接的情况,按一下开发板的复位键即可 3.成功 |
|
|
|
只有小组成员才能发言,加入小组>>
3314 浏览 9 评论
2995 浏览 16 评论
3494 浏览 1 评论
9059 浏览 16 评论
4088 浏览 18 评论
1178浏览 3评论
605浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
599浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2335浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1896浏览 2评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 03:26 , Processed in 1.554727 second(s), Total 79, Slave 60 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号