基础实验-LED指示灯实验
本以为这个会很简单,分分钟解决的,但是没想到会遇到问题,而且困扰了一晚上,详见http://forum.eepw.com.cn/thread/256935/1
在之前工程模板的基础上再BSP分组中增加LED.c和LED.h,并将LED.h包含到common.h中
LED IO配置
/************************************************************************\ * 函数名:LED_Initialization * 函数功能概述:LED初始化 * 参数说明: * 返回值说明: \************************************************************************/ void LED_Initialization(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);//使能时钟 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //PB3:D1 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); //PC13:Dx GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); LED_D1_OFF(); LED_Dx_OFF(); }
添加宏定义
#define LED_D1_ON() GPIO_ResetBits(GPIOB, GPIO_Pin_3) #define LED_D1_OFF() GPIO_SetBits(GPIOB, GPIO_Pin_3) #define LED_Dx_OFF() GPIO_ResetBits(GPIOC, GPIO_Pin_13) #define LED_Dx_ON() GPIO_SetBits(GPIOC, GPIO_Pin_13)
这样就可以控制LED了
关于时钟
在串口之前,先说说时钟配置。时钟很重要,尤其对于通讯来说,比如串口的波特率。
在启动代码中(startup_stm32f10x_md.s)复位的程序入口Reset_Handler:
程序首先进入SystemInit函数,在跳转到main函数。右键SystemInit再选择goto definition可以看到跳转到system_stm32f10x.c中的SystemInit函数,这个函数就是进行时钟配置。但是库中默认外部晶振为8MHz,但是四轴外部晶振为16MHZ,所以我们最好还是自己重新配置时钟。
/************************************************************************\ * 函数名:RCC_Configuration * 函数功能概述:时钟配置 * 参数说明: * 返回值说明: \************************************************************************/ void RCC_Configuration(void)//时钟配置 { ErrorStatus HSEStartUpStatus;//判断标志变量 RCC_ClocksTypeDef RCC_ClocksStructure; RCC_DeInit(); RCC_HSEConfig(RCC_HSE_ON);//使用外部时钟 HSEStartUpStatus = RCC_WaitForHSEStartUp();//等待外部时钟稳定 if(HSEStartUpStatus== SUCCESS)//如果外部晶振启动成功 { RCC_HCLKConfig(RCC_SYSCLK_Div1);//HCLK(AHB时钟)值等于系统时钟 RCC_PCLK1Config(RCC_HCLK_Div2);//PCLK1(APB1时钟)值等于HCLK的一半,最高不超过36MHz RCC_PCLK2Config(RCC_HCLK_Div1);//PCLK2(APB2时钟)值等于HCLK,最高可是72MHz FLASH_SetLatency(FLASH_Latency_2);//FLASH时序控制,SYSCLK0~24MHz Latency=0.SYSCLK25~48MHz Latency =1.SYSCLk 48~72MHz Latency=2 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//开启FLASH预取指功能 RCC_PLLConfig(RCC_PLLSource_HSE_Div2,RCC_PLLMul_9);//HSE提供系统时钟,9倍频,也就是72MHz RCC_PLLCmd(ENABLE);//启动PLL while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);//等待PLL稳定 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//系统时钟来自PLL输出 while(RCC_GetSYSCLKSource()!=0x08);//等待系统时钟稳定 } //检测 RCC_GetClocksFreq(&RCC_ClocksStructure); }
但是还有一个问题,通过RCC_GetClocksFreq函数程序认为的系统时钟是36MHz,如果这样使用库函数配置波特率实际会与设定差一倍。这是因为在stm32f10x.h中宏定义了HSE_VALUE,这个值是8M,所以用我们要把这个宏定义改为16000000,这样就可以了。注意修改这个文件需要先将文件的只读属性去掉
基础实验-UART串口通讯实验
给出关键函数
/************************************************************************\ * 函数名:USART1_Initialization * 函数功能概述:串口1初始化 * 参数说明:baud-波特率 * 返回值说明: \************************************************************************/ void USART1_Initialization(uint32_t baud) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);//使能时钟 //PA9-TXD GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); //PA10-RXD GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = baud; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_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_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); } /************************************************************************\ * 函数名:USART1_SendByte * 函数功能概述:串口1发送字节 * 参数说明:data-数据 * 返回值说明: \************************************************************************/ void USART1_SendByte(uint8_t data) { USART_SendData(USART1, data); while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} }
主要是配置好IO复用,USART的波特率,数据位,停止位等等,就可以了
基础实验-PWM电机驱动实验
PWM是电机驱动的基础,也是控制的基础。简单来说就是改变占空比来改变方波的等效电压,所以占空比越大,等效电压越大,电机也就转的越快。
下面给出配置代码
/************************************************************************\ * 函数名:TIM2_Initialization * 函数功能概述:PWM初始化 * 参数说明: * 返回值说明: \************************************************************************/ void TIM2_Initialization(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //PA0-1-2-3:PWM GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 100; TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)((36000000 / 1000000) - 1);//1MHz TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* PWM1 Mode configuration: Channel1 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM2, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); /* PWM1 Mode configuration: Channel2 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC2Init(TIM2, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); /* PWM1 Mode configuration: Channel3 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC3Init(TIM2, &TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); /* PWM1 Mode configuration: Channel4 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC4Init(TIM2, &TIM_OCInitStructure); TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM2, ENABLE); TIM_Cmd(TIM2, ENABLE); }
PWM是通过定时器模块产生的,首先配置定时器的基础部分,分频、计数模式、溢出值等等,在配置各个通道的输出方式,初始的比较值等等,因为是上电初始化,所以TIM_Pulse = 0;
通过TIM_SetCompare1等函数就可以改变通道的比较值,也就改变了PWM的占空比。
int main(void)
{
int32_t i;
Hardware_Initialization();
USART1_SendStr(" QuadCopter DIY\r\n");
while(1)
{
LED_Dx_ON();
LED_D1_OFF();
Wait_for(100);
LED_Dx_OFF();
LED_D1_ON();
Wait_for(100);
USART1_SendNum(i++);USART1_SendStr("\r\n");
TIM_SetCompare1(TIM2, i % 30);
TIM_SetCompare2(TIM2, i % 30);
TIM_SetCompare3(TIM2, i % 30);
TIM_SetCompare4(TIM2, i % 30);
}
}
MPU6050的官方网站地址
http://www.invensense.com/mems/gyro/mpu6050.html
可以在上面下载数据手册还有寄存器地址(竟然还把两个分开,最开始下载数据手册里没有找到寄存器说明还很纳闷呢)
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图四被打赏50分 | |
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 |