tag 标签: stm32

相关帖子
相关博文
  • 热度 1
    2017-8-9 14:38
    417 次阅读|
    0 个评论
    制作小四轴的计划 经过几个月的学习,STM32算是入门了,外设也会用了,但是…,给一个项目的话还是感觉无从下手,还是不会设计程序的架构,不知道如何再裸奔不带系统的情况下,让各个模块协调的运作起来。所以,我发现我急需要一个完整的项目来练练手了,当然这个项目一定是能够从头到尾的做下去的。以前也试过做项目,或者是因为遇到某一个问题无法解决,或者是不知道怎样建立程序的整体构架,最后都不了了之…… 机会来了,偶然之间发现的一个工程师的秘密基——摩尔吧,有一个指导做四旋翼的系列视频教程,西安小马哥讲的,用的正是STM32MCU,从散件焊接到程序编写,都很详细,对,这正是我现在急需的项目实战机会,真是急人之所急,在此非常感谢小马哥的奉献,抱拳、抱拳。 这个项目涉及到了STM32的很多功能和外设:GPIO、USART、IIC、SPI、ADC、DMA、TIM,还涉及到了一些其它功能模块:蓝牙、NRF24L01、MPU6050等,还能学习PID算法,真是练手神器啊,于是我就按照小马哥课程安排,给自己做了一个计划——两个月跟着小马哥的视频让四旋翼飞起来,具体计划如下: ​ ​ 当然啦,不出意外,依然是每两天写一篇文章发表到公众号,记录制作和学习的过程。 已经有了计划,当然是立马行动了,咔咔咔,已经购买了散件和一系列工具,坐等到货,就开干,先放一张图,给自己打打气…… 如果有写的不合适的地方,还请大家多多指教。如果你有兴趣,也可以一起互相学习,共同进步。 (微信号 :c18093458455)
  • 2017-8-9 14:34
    1587 次阅读|
    0 个评论
    四旋翼如果驱动电机,定时器的PWM输出定然是必不可少的,今天的内容是跟着小马哥的视频,完成高级定时器1的4路PWM输出和如何使用Keil自带的仿真功能检验输出的PWM波。 要使用定时器输出我们需要的PWM,就要会配置定时器。我们直接看高级定时器的功能框图,从框图上看定时器都需要哪些配置: 图中的红色箭头表示一条通道,我们配置好这条通道沿线的寄存器就能输出我们需要的波形了,这条通道上,我标注了三个区域:1、2、3,这三个区域就是需要配置的: 区域1:时钟源选择,我们通过RCC_APB2PeriphClockCmd()就可以选择内部时钟源作为定时器的时钟; 区域2:这里主要是设置时基,通过自动重装载寄存器(TIMx_ARR)、计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)进行设置。对应库函数中的TIM_TimeBaseInit()函数,通过这个函数设置计数模式、预分频数、计数次数等,就可以得到我们想要的计时时间,比如我们要定时1s、1us,这个时间的长度就是通过在这个区域设置的,定时公式为: T = (TIM_Period +1) X (TIM_Prescaler +1)/TIMxCLK ; TIM_Period是计数次数,也就是自动重装载中的值,TIM_Prescaler是预分频系数,是预分频器中的值,TIMxCLK是时钟。 区域3:这个区域是输出比较通道的配置,包括输出比较的空闲模式、输出比较模式、极性、输出状态、捕获/比较寄存器等的设置,对应库函数的TIM_OCxInit()函数,其中捕获/比较寄存器是一个16位寄存器,装的是当前捕获/比较寄存器的值,通过设置这个值,我们就可以得到不同占空比的PWM。 另外,除了这些设置,我们还需要使能自动重装载寄存器ARR的预装载功能,失能捕获/比较寄存器CCR的预装载功能,对应的库函数为: TIM_ARRPreloadConfig(TIM1, ENABLE); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); 失能CCR的预装载功能后,写入的值会立即传到捕获/比较寄存器,不用等到更新事件的发生。 其他的配置就不介绍了,大家可以参考官方例程。 配置好定时器后,我们怎样知道,到底有没有PWM输出呢,检测方法有好几种,视频中介绍的是利用Keil自带的仿真功能,下面我们就说说,这个仿真功能怎么使用: 步骤: 第一步:配置好定时器,运行程序,并且没有错误; 第二步:点击工具栏的“Options for target”,选择Debug选项卡,进行如下设置: 第三步:点击工具栏的“Start/Stop Debug”快捷键,然后点击“Setup”,进入下面的界面,点击红框表示的位置,添加仿真通道: 需要添加四次,即添加四个通道,因为我们有四路输出,添加通道的名称分别为:PORTA.8、PORTA.9、PORTA.10、PORTA.11,我们TIM1的四个输出通道是GPIO_8,GPIO_9,GPIO_10,GPIO_11,通道添加好后,点Close; 第四步:此时,已经有四个通道了,我们需要设置输出通道为数字输出,方法是:鼠标右键点击下图红框所示位置,选择bit即可,每一路都要设置; ​ ​ 第五步:点击工具栏的“Run”,启动仿真,就看到有四路输出了,神不神奇? 今天的内容到这里就结束了,真是收获满满呀…… 如果有写的不合适的地方,还请大家多多指教。如果你有兴趣,也可以一起互相学习,共同进步。 (微信号 :c18093458455)
  • 2017-8-9 14:32
    365 次阅读|
    0 个评论
    今天跟着视频学习了位运算,感觉很有用,这里分享给大家。 位运算 位运算主要有:位与运算符()、按位或运算符(|)、异或运算符(^)、取反运算符(~)、左移运算符()、右移运算符()等,下面我们分别介绍这几个位运算的用法及其在程序中的运用。 (1)位与() 按位与运算符“”是双目运算符。其功能是参与运算的两数各对应的二进位相与。两个数相“与”时,如果两个位同时为1,则结果为1,否则为0,即:11=1,10=0,01=0,00=0。 比如:0xc30x11计算如下 在STM32编程中位与()运算可以作为条件判断之用,请看下面的程序: uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin),这是STM32库中的函数,用来读取输出的某个引脚的电平,运行一下”Go To Definition”,你会发现下面的语句: if ((GPIOx-ODR GPIO_Pin) != (uint32_t)Bit_RESET),当然对应的GPIOx-ODR是输出数据寄存器的值,是16位的数值;GPIO_Pin也是STM32库定义的16位类型的数据。 (2)位或(|) 按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的两个二进位有一个为1时,结果位就为1,即:1|1=1,1|0=1,0|1=1,0|0=0。 比如:0xc3|0x10 在STM32编程中位或运算(|),可以作为置位之用,因为位或运算不会改变影响原来数值的其它位,上面的0xc3|0x10,原来的0xc3(b11000011),只有一个位发生了改变。请看下面的程序: GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1;这是常见的对两个引脚按位或,在STM32库中,GPIO_Pin_0和GPIO_Pin_1其实也是两个整数,请看它们的宏定义: #define GPIO_Pin_0               ((uint16_t)0x0001)   #define GPIO_Pin_1               ((uint16_t)0x0002)   (3)异或(^) 两个二进制数进行异或,若对应的位不相同,则结果为1,否则为0,即:0^0=0,0^1=1,1^0=1,1^1=0; 比如(0xc3 ^ 0x10) ^ 0x10 ​ ​ 从上面的式子中大家发现了什么,对,0xc3与0x10第一次异或,发生一次改变,且只改变了与0x10相关的位,并且如果与同一个数两次异或,它就恢复到初始值,所以异或(^)具有翻转的功能,在程序中可以当做开关使用,比如,让一个LED灯点亮和熄灭就可以用这种方法: GPIOA-ORD ^= GPIO_Pin_1;     //LED1灯熄灭 Delay_ms(100); GPIOA-ORD ^= GPIO_Pin_1;     //LED1点亮   (4)取反(~) 这是个单目运算符,二进制位取反,如果1取反,结果为0,0取反,结果为1,即:~0=1,~1=0。 程序中取反(~)和按位与()相结合,会有复位的效果。 比如0xd3(~0x10) (~0x10)结果为b11101111,再和0xc3按位与:  是不是达到了复位的效果呢? (5)左移运算符() 左移运算符用来将一个数的各二进制位全部左移若干位,后面补0,移出的位被丢弃,相当于乘2运算,因为位运算比乘法用算快,所以可对一个代码进行优化。 比如0x018,结果为b100000000,就是1后面补8个0,移位运算符在通信时,接收数据时很有用。 (6)右移运算符() 右移运算是将一个二进制位的操作数按指定移动的位数向右移动,移出位被丢弃,对于左边移出的空位,如果是正数,则一律补0,如果是负数,则可能补0,也可能补0,这由不同的机器决定。 这个运算符可以用来获取一个16位数据的高8位,比如:要获取0x1111的高8位,0xcc118,便可得到高8位0xcc。 到这里,今天的内容就结束了。 如果 有写的不合适的地方,还请大家多多指教。如果你有兴趣,也可以一起互相学习,共同进步。 (微信号 :c18093458455)
  • 2017-7-17 14:07
    711 次阅读|
    0 个评论
    STM32单片机的堆栈自顶向下,从符号__initial_sp开始,到符号STACK结束。 如果函数内部定义了大数组,或者参数传递过深,就会造成堆栈溢出,且它无法被编译器检测出来。 有一种运行时检测堆栈的方法: 使用readelf工具,读出alf文件的符号表; 找到临近符号表的最后一个数据结构,为其增加一组变量,赋特定值; 在系统定时器里,持续检测这些值是否被改变。
  • 2017-5-30 13:10
    825 次阅读|
    0 个评论
    刚入电源坑的菜鸟一枚,开个日记记录下自己学习电源的过程及心得。 第一个独立项目: 程控可调线性稳压电源 设计目标: 输入AC 220V 两路输出电压0~15V可调,输出最大电流:1A。 带过流保护功能,电压步进0.1V。 以下是本次制板所遇到的问题 1.有大电流通过的测量线要足够粗,防止线上损耗电能。对于电子负载,经过大电流时,线端的电压会明显低于板端电压,这时候要以着重测量板端电压为准。同样,在测试时DC-DC部分时,外部输入电源与板子连接的线也要足够粗。我在测试时发现该电源DC-DC部分负载调整率很差,输出电流刚过0.5A,输出电压就会掉下去大概1V。后来测试时发现有两个问题:一是我是以电子负载显示的数值为准,而PCB板与电子负载之间连接的导线很细,这就导致有大电流经过时,导线上回损失一部分电压,因此应以板端电压为准。二是我发现外部电源的地与PCB板上的地有1V多压差。刚开始很迷惑,后来想到我是用杜邦线连接的外部电源与PCB,这样做太不专业了,将外部电源的输出线直接接到PCB板上后,这个压差消失,电源的负载调整率有了极大的改善。因此测试电源时也有许多需要注意的地方。 2.电源的输出电压反馈分压电阻上接入电容的取值不合适会引起震荡,需复习零极点分析。 3.绘制元件封装时不能只考虑焊盘位置,还要考虑元件本身占用的大小。 4. 绘制变压器封装的时候遇到了一个坑,网上给的图是变压器从底下向上看的图,我当成了变压器的俯视图,结果导致我画出来的封装与实际封装成一个镜像,做出板子后才发现这个问题。以后要注意。 altium使用技巧: 本次制板经历使我掌握了altium里更多的技巧,比如多通道设计,对铺铜的设计等等,在此进行归纳: 1.修改局部铺铜,铺铜时候手抖一下可能就导致铺铜的形状让人不满意,可以右键--ploygen action--move vertains.来细微调整铺铜形状。 2.slice ploygen pour 可以将一整块铺铜切割成两块,可以用来隔离模拟地和数字地。 3.铺铜比放置fill好很多,因为铺铜可以通过重新铺铜来方便地调整形状,Fill不行。 4.Ctrl+D 在弹出的窗口中可以隐藏铺铜,方便设计 5.PCB编号后与原理图的匹配办法: 在PCB中对元器件进行重新编号以后,即PCB中选择Tool - Re-annotate,选择编号路径后,保存文件; 系统自动生成一个后缀为WAS的文件; 打开SCH文件,选择Tool - Annotate Schematics - Back Annotate,在弹出的对话框中选择,PCB生成的.WAS文件; 选择Accept Change( Create ECO ),则原理图中元件标号更新成功;
相关资源
广告