×
单片机 > 单片机程序设计 > 详情

拥抱ARM妹纸第二季 之 第二次 约会需要浪漫,这么大灯泡怎么弄?

发布时间:2020-05-27 发布时间:
|

终于轮到俺的小穆出场啦。有请能让太阳也为之暗淡的小穆闪亮登场~,鼓掌吧,欢呼吧!~~

♪♪ We can burn brighter Than the sun ~~~ ♪♪

“谢谢~~~“ 唱的太棒啦,再来首~~  再来首~~  

”谢谢大家,为大家表演《遮天蔽日》魔术“ 

!@%&……¥%!@!@#……¥@#¥%@#¥!@!!%%……¥%……&¥(咒语)

 

 ... .... 场内一片漆黑,只看到3个省略号~~~

番茄或鸡蛋可以丢,硬东西可乐罐之类不要丢啊!划伤俺小穆可爱的脸,哼哼~和你们拼命!

好吧,不玩啦~!

 

对小穆来说,PWM输出那是小菜一碟。小穆对木?嗯嗯!哇咔咔~~~ 连代码都不用写就能实现的喔!。

 

可以直接通过TIM中的设置,实现PWM的输出!

“啥??PWM?PWM是什么东东??”

“怎么连这个都不知道!! 就是小穆唱歌的节拍呗。”

官方点就是“脉宽调制”,这可是个很有用的东西,很多东西都可以用这进行调节。如马达的转速,当然还能调节LED亮度。具体可以搜搜网上有非常详尽的说明。

 

拿出《小穆妹纸攻略手册》,找到TIM2-TIM5。

上面的是TIM2 到 TIM5 的原理图。手册上TIM1排在前面,感觉怪怪的。TIM1前面扣这一顶“高级”的帽子,那货对俺来说高级功能暂时不用,所以直接忽视→_→。TIM2的图比较简单。

小穆现在不在!偷偷告诉你,俺看了这图N遍啊~N遍~~,才有了大致了解。女人心海底针,想要了解真不容易。

 

看看,这个图要比时钟配置简单多了。按照上面俺把她划分成三块。

  1、RCC输入                         ---  为产生节拍提供基准

  2、时基单元                         ---  小穆的心跳节拍器,1/4拍是多长呢?

  3、捕获比较输入输出通道    ---  跟随着节拍,唱出你的快乐吧。

看着图就能知道,俺的小穆有多强大。一个时钟能同时控制4路通道,就是4个IO口~(≧▽≦)/~啦啦啦。蓝色区域左手边是监听耳麦(输入捕获的),右手边是麦克风(比较输出的)。

“通道在那个IO引脚上?”

“打开MicroXplorer,设置TIM1-4 为PWM输出,所有通道对应IO一目了然。这太简单了,比看葵花宝典清晰不知道多少倍!”

 

 

按照刚才看妹纸使用手册,就大致能知道怎么处理过程。主要6步就能搞定。

 

PWM设置步骤

  1、确定那个TIM输出PWM

  2、使能总线 IO口和TIM

  3、使能IO口,设置复用输出

  4、使能TIM,设置输出比较模式

  5、设置时基TIM寄存器

  6、设置TIM产生通道的相关寄存器

 

按照上面的步骤还是很多,寄存器一大把。抓头发吧~~~ 大头了吧~~。俺有个超级法宝“IDE调试器”,这个东东可以居家旅行必备神器。PWM是直接通过配置获得,这种情况下。嘿嘿~~ 直接运行空程序,进入调试状态。小弟用KEIL,所以...

 

 

控程序当然也不是完全空,至少已经设置好晶振。这个是小穆妹纸标准行头(模板),拥抱小穆妹纸第一季的珍贵遗产。

整个代码设置基本的时钟单元,int main(void) 函数就只有让小穆无限劳碌命的一句话。

 

----------------------------------------

#define STM32F10X_MD#include void SystemInit(void)
{
    unsigned char dump = 0;    
    // 使用外部8MHz晶振,启用PLL设置系统时钟为 72HMz    // USB 可用    // APB1 低速总线 36HMz    // APB2 高速总线 72HMz
    RCC->CFGR = 0x001D0402;
    RCC->CR   = 0x01010083;    
    // 闪存访问延迟,48MHz ~ 72MHz = 010。 复位值:0x30
    FLASH->ACR = 0x32;    
    // 确定外部高速晶振起效
    while (!(RCC->CR>>17));    // 确定PLL设置起效
    while (!(RCC->CR>>25));    // 确定PLL为系统时钟源
    while(dump != 0x02) {
        dump = RCC->CFGR >> 2;
        dump &= 0x03;
    }              
}int main(void)
{    while (1);
}

----------------------------------------

译开关 STM32F10X_MD

    这个模板只适合 STM32F101~3 Flash 64~128K,具体参见参考手册(RM0008 V14 英文版)第2.2章。中文版没找到类似说明,应该是翻译版版本太旧。STM头文件中也有类似说明,可以直接删除此行,就能定位到。第一季里有详细说明。

 

启动调试后所有小穆妹纸的心思,那是一目了然。

 

如俺想打开TIM2通道2的PWM进行输出。按照下面红色圈圈的位置打开设置,想要的PWM的设置完成啦。可以看到那些寄存器的值,就是最终需要设置的结果哦。这竟然时如此之的简单。

 

 

想看看效果这容易,打开逻辑分析界面。就能看到有条线在上下跳动。

1、打开逻辑分析界面,

2、打开设置对话框

3、加入需要监视的引脚(如:PORTA.1) 

4、设置按BIT(电平方式)显示。颜色改个热辣的红?

 

“我什么都没看到。”

“我就看到一坨颜色”

“难道就是传送中国王的新衣,只有聪明的人才能看到?"

 “图片圈圈2位置,右边→_→看,有个Zoom,点点下面 缩小(In) 或 放大(Out)试试。应该就能看到。”

 “还是看不到?"

看来要找找问题,监视的引脚不对?TIM使使能没?IO口使能没?总线使能没?重头到尾过一遍。

 

按照上面的设置,可以看到实际原理图大致对应寄存器位置。

 

 

“PWM输出多少频率还是不清楚?”

“第四和第五个圈圈,是设置实际频率的位置。”

每次从1数到100,到100后从头再数。这个就是“时基单元”干的活。至于想用啥鸟语数,这个俺不管啦,反正小穆听得懂就行。

数到多少让小穆脉动一下呢,如到50后脉动一下?设置“捕获比较寄存器” 。那么数到50后,小穆用犀利的眼神盯着我,让给买奶茶。

“那设置0呢,或是俺调皮一下设成101,或999999,会发生什么情况?”

“好吧,我太牛了。试试会发生什么事情!”

 

数数还有很多方法,如倒着数,顺着数,双数数...,那种能让你心动,就可以用那种。想了解更多,参见葵花宝典!反正我只要顺着数就行了。

 

玩够了,俺准备直接把这些值使用盖世神功“啃秋四,啃秋五”全部抄袭下来。

----------------------------

int main(void)
{
    unsigned int x, y;
    unsigned char iDir;
    unsigned int pwmwidth;    
    // 总线 TIM2 和 A组引脚 使能
    RCC->APB1ENR = 0x00000001;
    RCC->APB2ENR = 0x00000004;    // PA1 脚使用复用输出,打开TIM2第二通道
    GPIOA->CRL = 0x444444A4;    // 设置自动重载计数器
    TIM2->ARR = 900;    // 设置PWM    //   通道2 PWM模式1    //   设置比较输出    //   设置比较脉冲宽度
    TIM2->CCMR1 = 0x6000;        
    TIM2->CCER = 0x0030;        
    TIM2->CCR2 = 0x0000;    // 设置为比较输出,使能TIM2
    TIM2->CR2 = 0x0030;
    TIM2->CR1 = 0x0001;
        
    
    iDir = 1;
    pwmwidth = 1;    
    while (1)
    {        // 延迟        //for (iDelay=0; iDelay  900) iDir = 0;        else if (pwmwidth CCR2 = 0;        else if (pwmwidth == 300)     TIM2->CCR2 = 300;        else if (pwmwidth == 600)     TIM2->CCR2 = 600;        else if (pwmwidth == 900)     TIM2->CCR2 = 900;
    }
}

通过PWM设置让LED切换亮度


 

免责声明:

   上面只是测试用代码不能作为正式代码使用。这种臭臭的coding,只有天知道写是是什么鸟玩意。当然如果你想让自己在几天后,完全不知道写的是啥,这是个不错好方法。

 

代码风情

   好的代码总是很优雅的,犹如妹纸的曲线。能让别人一看就知道你的思路。当然这个要求可能比较高,但是一定要有这个目标在。一般对硬件操作有2中,一种是用官方提供的库,一种是直接操作寄存器的。

    第一种 固件库 (☆推荐☆)

        使用库方法,很多教学中都基本都会使用。优点是不用关心寄存器易于移植可读性高。有一套标准的函数命名规范,非常容易记忆。优点很多,小问题也是有的。函数库版本问题,容易困扰初学者。对公司级应该这不是很大问题。

 

    第二种 直接寄存器操作

        测试代码中的例子是粗暴型控制寄存器的方法,还种是相对固件库类似的方法。用常量定义控制寄存器。在头文件中都会有定义寄存器相关的常量。命名规则和固件库函数命名规则一致。这种方式代码的可读性要比粗暴型的高很多。如打开TIM1时钟 TIM2->CR1 |= TIM_CR1_CEN 这句话肯定要比 TIM2->CR1 |= 1  更容易理解。

 

    可能你会问,为什么我要中这种自己都不推荐的方法来coding?其实也是蛮简单的,本身有一定的工程开发经验,xx模式之类有一定了解。所以更想侧重了解硬件,粗暴型控制能更容易了解硬件。后续代码还是以直接操作寄存器,当然不是数字型粗暴模式,而是常量型温柔模式。原有百年不变的东西(模板),直接忽视→_→。

 

    在整个产品中硬件控制只是一部分,还有一部分是功能实现。团队合作那么就要以团队为准,如果就你一个人项目就看你自己的拿捏。自己的代码风格对以后影响深远。

 

    具体相关的代码风格的文章很多,这里提就是怕被我带坏。只能忍痛在妹纸篇里插播免责声明。

 


 

(⊙o⊙)…~~ 跑题啦!小穆拉长了脸,写着一脸的讨厌。( ˇˍˇ )

 

用个LED做个测试瞅瞅,效果如何。

 

嗯嗯,效果不错。


关键字:ARM  灯泡 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机中高阻态的实质及意义