发个贴,记录一下每天的所得。
手上有一块 STM32f103zet6的最小系统板,示波器、电压表齐全。把收获和问题都记录下来
开始,stm32IO口有八种输入输出模式:
浮空输入
上拉输入
下拉输入
模拟输入(ADC采样用的就是这个模式)
开漏输出(开漏输出本身没有输出能力,使用的话必须外接上啦电阻,根据Vcc的不同,直接决定开漏输出的输出能力)
推挽输出
复用开漏输出
复用推挽输出
要点亮一盏LED灯,首先要使能相应的时钟。
stm32内部的总线时钟是通过外部晶振经过倍频得到的,通常为了功耗的考虑,这些总线是被关闭的。只有当开启了总线时钟,总线才被打开。
GPIO属于APB2总线,总线时钟为72MHz,是外部晶振经过9倍频得到的。
初始化LED,先初始化GPIO.
板子上的LED有两个,PE5和PE6.
void LED_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_STRU;//定义一个结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//开启GPIOE时钟
GPIO_STRU.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6;//设置管脚为5和6脚
GPIO_STRU.GPIO_Mode=GPIO_Mode_Out_PP;//设置为推挽输出(一般IO口应用都这样设置)
GPIO_STRU.GPIO_Speed=GPIO_Speed_2MHz;//输出速度2Mhz足以
GPIO_Init(GPIOE,&GPIO_STRU);//初始化
GPIO_SetBits(GPIOE,GPIO_Pin_5);
GPIO_SetBits(GPIOE,GPIO_Pin_6);
}
8
|
|
|
|
初始化IO口之后把电平设置为高电平,不然初始化之后灯就会亮起,这显然和想要的初始化LED的效果不符。
IO口初始化之后,如果配置成输出模式,IO的电平状态由DR寄存器决定。而DR寄存器是复位后置0的。所有IO口初始化后,会变成低电平
|
|
|
|
|
果然,回归了自己探索电路的时候,问题层出不穷。
1、不要随便使用switch语句。
楼主使用switch出现错误,没有找到原因。这里贴一下,大家看看。
void LED_On(u8 num)
{
switch(num)
{
case 1:
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
case 2:
GPIO_ResetBits(GPIOE,GPIO_Pin_6);
default:
break;
}
}
|
|
|
|
|
新技巧,调用库函数操作io口速度比较慢,在一些对时间精确要求高的情况下不使用,
stm32专门为IO口提供了两个寄存器BSRR和BRR。BSRR对应置1,BRR对应清0.
GPIOE->BSRR=0x80;把PE7置1
GPIOE->BRR=0x80;把PE7清0
挺好用的
|
|
|
|
|
取反操作技巧
GPIOE->ODR^=0x20;//异或,取反PE5
|
|
|
|
|
stm32的串口配置很简单,本来在其它单片机还需要细心的计算一下波特率等参数需要的寄存器值的配置。但是在stm32强大的固件库的支持下。配置波特率,只需要简单的
UART_structure.USART_BaudRate=Rate;
非常便捷的设置波特率。
值得一提的是keil支持微库的使用。
int fputc(int ch, FILE *f)
{
USART_SendData(USART1, (unsigned char) ch);
while (!(USART1->SR & USART_FLAG_TXE));
return (ch);
}
我们可以使用重定向fputc函数,来使得printf函数的使用变得可能。
这样一来,调试一些比如ADC此类具有大量数据需要查看的设备很便捷。
毕竟printf可以带参数输出。推荐大家这样使用串口。
|
|
|
|
|
stm32的串口RX管脚采用的过采样的方法,来区分数据和噪音。这里很明显是采用的类似ADC的办法,不知道为什么其引脚配置成了浮空输入模式。本来按我的猜想应当是模拟输入模式才对
。。
|
|
|
|
|
遇见一点小问题,这个最小系统设计的时候没有串口。本来我想杜邦线接出来接到我自己的一个串口模块上,但是不知道为什么一外接,板子就没有办法正常启动。。
发一下板子原理图,大神给看看呗
|
|
|
|
|
受教了 ,水平有限
|
|
|
|
|
刚刚做了一下pwm输出的实验,在示波器上输出了一个72khz的方波。只是频率略有不稳定,有0.1khz的误差。勉强接受吧。
void PWM_GPIO_Init()
{
GPIO_InitTypeDef GPIO_structure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
GPIO_structure.GPIO_Pin=GPIO_Pin_0;
GPIO_structure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_structure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_structure);
}
void PWM_Mode_Init(u32 time,u32 aver)
{
TIM_TimeBaseInitTypeDef TIMEBASE_structure;
TIM_OCInitTypeDef TIMOC_structure;
TIMEBASE_structure.TIM_Period=time;//计数值,参数传入,方便设置
TIMEBASE_structure.TIM_Prescaler=0;//预分频值为0,72MHz
TIMEBASE_structure.TIM_ClockDivision=TIM_CKD_DIV1;//时钟分频,展开为0
TIMEBASE_structure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseInit(TIM3,&TIMEBASE_structure);//时基定时器初始化
TIMOC_structure.TIM_OCMode=TIM_OCMode_PWM1;//PWM模式1,计数值小于预设置值是为有效电平
TIMOC_structure.TIM_OutputState=TIM_OutputState_Enable;//输出有效
TIMOC_structure.TIM_Pulse=aver;//跳变值,参数传入,用来控制占空比
TIMOC_structure.TIM_OCPolarity=TIM_OCPolarity_High;//高电平为有效电平
TIM_OC3Init(TIM3,&TIMOC_structure);//使能定时器3的通道3
TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能通道3的重装载寄存器
TIM_ARRPreloadConfig(TIM3,ENABLE);//使能定时器3的重装载寄存器
TIM_Cmd(TIM3,ENABLE);//使能定时器3
}
void PWM_Init(u32 ti,u32 ar)
{
PWM_GPIO_Init();
PWM_Mode_Init( ti,ar);
}
|
|
|
|
|
本来楼主是用的野火m3的板子,也学了一段时间,感觉会的挺多。结果接触了一个小项目的开发,才认识到自己的不足,用野火的开发板,只是学会了使用它帮你移植好的各种强大的例程。才决定拿一块最小系统,重头弄起。
|
|
|
|
|
少了break
case 1:
GPIO_ResetBits(GPIOE,GPIO_Pin_5);break;
case 2:
GPIO_ResetBits(GPIOE,GPIO_Pin_6);break;
|
|
|
|
|
找了一块触摸屏,开始探索fsmc接口驱动液晶的方法。
|
|
|
|
|