数码之家

 找回密码
 立即注册
搜索
查看: 5711|回复: 9

[STM] 我的STM32F030核心板及三种PWM实现呼吸灯的方法

[复制链接]
发表于 2020-3-10 16:03:56 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 网络孤客 于 2020-3-10 16:36 编辑

不是所有芯片都有开发板,官方会比较齐全,但价格也上来了。
虽然打板比较便宜,但前期研究电路不确定。
还是充分利用STM32外围原件简单的优势,自己搭建核心板。
材料:芯片,SSOP20转DIP20转接板

微信图片_20200310121033.jpg

焊接好
微信图片_20200310110526.jpg

外围电路图,只做了上电复位电路和boot0电路
电路图.jpg

搭好电路后测试
微信图片_20200310110554.jpg

不想只点个灯,还是玩呼吸灯吧!
CUBEMX中设置时钟48MhzTIM3Channel1“PWM Generation CH1”
cubemx.png

预分频47,重装值为999,这样PWM信号周期约为1毫秒
Pulse值为0,这个是占空比,计算方式:
占空比= Pulse /(重装值+ 1)*100%
相关设置网上资料有


开启PWM
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);                    //开启PWM
修改Pulse值(也就是CCRx)
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,pwmVal);    //修改比较值(Pulse),修改占空比
或:
TIM3->CCR1= pwmVal;


方式一:采用延时方法实现
搜到网上采用延时方法实现呼吸灯,程序如下:

int main(void)
{
......
uint16_t pwmVal=0;   //PWM占空比
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);                    //开启PWM
......
while (1)
{  
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
    /*
    while (pwmVal <1000)
    {
      HAL_Delay(1);   //延时1ms
      pwmVal++;
     __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwmVal);    //修改比较值,修改占空比
     //TIM3->CCR1 = pwmVal;
    }
    while (pwmVal)
    {
      HAL_Delay(1);
      pwmVal--;
     __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwmVal);    //修改比较值,修改占空比
    TIM3->CCR1 = pwmVal;
    }
  }

方式二:采用中断方法实现
我对延时天生有种反感,效率有点低,改用中断!
在CUBEMX中把TIM3中断打开
全局变量
uint16_t pwmVal=0;   //PWM占空比
uint8_t pwmDir =0;         //变化方向

int main(void)
{
......
HAL_TIM_Base_Start_IT(&htim3);                //开始中断
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);                    //开启PWM
......
while //循环啥也不写
}

//写回调函数,这个是计数器达到重置值时激活
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (pwmDir == 0)
  {
    pwmVal++;
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,pwmVal);    //修改比较值,修改占空比
    if (pwmVal == 999)       pwmDir = 1;
  }
  else
  {
    pwmVal--;
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,pwmVal);    //修改比较值,修改占空比
    if (pwmVal == 0)  pwmDir = 0;
  }
}

方式三:采用中断方法实现所有IO口都能输出PWM
我突然发现PA6要用于SPI接口,是否能用其他IO口输出,STM32时钟输出基本与SPI重叠,只剩一个PB0,不够用。
(为了测试方便我用PA5与PA7做实验,其实可以任意IO口)
思路是当计数器达到预置比较值时产生一个中断,设置IO口,当达到重置值时再产生一个中断,反转IO口输出。
在CUBEMX中设置时钟48Mhz,TIM3的Channel1为“PWM Generation No Output”,把IO口还原出来。
为了更好效果,程序中两灯状态刚好相反


为了程序简约,我在main.h中宏定义
#define LED_Toggle   HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
#define LED_ON         HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin, GPIO_PIN_RESET);
#define LED_OFF        HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin, GPIO_PIN_SET);
#define LED2_Toggle  HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
#define LED2_ON       HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin, GPIO_PIN_RESET);
#define LED2_OFF      HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin, GPIO_PIN_SET);

int main(void)
{
......
HAL_TIM_Base_Start_IT(&htim3);                //开启中断
HAL_TIM_PWM_Start_IT(&htim3,TIM_CHANNEL_1);                 //开启PWM中断
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);                    //开启PWM
......
while //循环啥也不写
}


//写回调函数,这个是计数器达到重置值时激活,由于PWM没输出,
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef*htim)
{
  if (pwmDir == 0)
  {
    pwmVal++;
    __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1, pwmVal);    //修改比较值,修改占空比
    if (pwmVal == 999)      pwmDir = 1;
  }
  else
  {
    pwmVal--;
    __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1, pwmVal);    //修改比较值,修改占空比
   if (pwmVal == 0)  pwmDir = 0;
  }
  LED_OFF;
  LED2_ON;
}


//这个回调函数是计数器达到比较值时激活,由于PWM没输出,
voidHAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
  LED_ON;
  LED2_OFF;
}

打赏

参与人数 4家元 +135 收起 理由
newnet1234 + 20 認真發帖
有点不烧 + 20 謝謝分享
家睦 + 80
人艰不拆了 + 15

查看全部打赏

发表于 2020-3-10 16:12:44 | 显示全部楼层
哈哈,不错啊,这个只是我不会玩
回复 支持 反对

使用道具 举报

发表于 2020-3-10 16:18:35 | 显示全部楼层
这个48Mhz是怎么回事?比如外边接个16Mhz晶振,它内部也能产生更高频率的时钟吗,这个是怎么做到的呢,我的arduino怎么就不行呢?:mad:

打赏

参与人数 1家元 +6 收起 理由
网络孤客 + 6 歡迎探討

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2020-3-10 16:26:58 | 显示全部楼层
人艰不拆了 发表于 2020-3-10 16:18
这个48Mhz是怎么回事?比如外边接个16Mhz晶振,它内部也能产生更高频率的时钟吗,这个是怎么做到的呢,我的 ...

你可以百度下stm32的时钟树,或者直接看手册,里边有块内容叫pll,或者锁相环,可以理解为倍频电路

打赏

参与人数 2家元 +15 收起 理由
网络孤客 + 5 歡迎探討
人艰不拆了 + 10

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2020-3-10 16:28:40 | 显示全部楼层
飞向狙沙 发表于 2020-3-10 16:26
你可以百度下stm32的时钟树,或者直接看手册,里边有块内容叫pll,或者锁相环,可以理解为倍频电路 ...

原来如此啊
回复 支持 反对

使用道具 举报

发表于 2020-3-10 16:33:11 | 显示全部楼层
人艰不拆了 发表于 2020-3-10 16:18
这个48Mhz是怎么回事?比如外边接个16Mhz晶振,它内部也能产生更高频率的时钟吗,这个是怎么做到的呢,我的 ...

里面有PLL,PLL由VCO,PD和LFP组成,VCO可以在外部电压的控制下产生非常宽范围的振荡频率,然后VCO的输出经过可设置的分频后与可设置分频后的外部基准时钟由鉴相器比相后产生线性于相差的输出信号,然后经过LPF后给VCO实现闭环。最终,VCO的输出将与输入的时钟呈现倍数频差。
STM32内部有PLL及其相关分频器电路,所以时钟发生极其灵活。你那个垃圾AVR还是算了吧。一般的8位机很少有非常强大的时钟功能的,至少老型号都没有。

打赏

参与人数 2家元 +20 收起 理由
网络孤客 + 10 谢谢帮我解围
人艰不拆了 + 10

查看全部打赏

回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-10 16:33:50 | 显示全部楼层
人艰不拆了 发表于 2020-3-10 16:18
这个48Mhz是怎么回事?比如外边接个16Mhz晶振,它内部也能产生更高频率的时钟吗,这个是怎么做到的呢,我的 ...

stm32f0系列48Mhz频率算比较低了,
而且不需要外部时钟就可以玩起来。
如果不是需要要到调试口,boot电路都可以去掉。

打赏

参与人数 1家元 +5 收起 理由
人艰不拆了 + 5

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 2020-3-10 16:34:05 | 显示全部楼层
la45088d1 发表于 2020-3-10 16:33
里面有PLL,PLL由VCO,PD和LFP组成,VCO可以在外部电压的控制下产生非常宽范围的振荡频率,然后VCO的输出 ...

哈哈,厉害了,不服不行啊:loveliness:
回复 支持 反对

使用道具 举报

发表于 2020-3-11 01:37:20 | 显示全部楼层
la45088d1 发表于 2020-3-10 16:33
里面有PLL,PLL由VCO,PD和LFP组成,VCO可以在外部电压的控制下产生非常宽范围的振荡频率,然后VCO的输出 ...

avr不知不觉都落后这么多了,stm32实在太强大了
回复 支持 反对

使用道具 举报

发表于 2020-3-11 22:54:21 | 显示全部楼层
zzy9903 发表于 2020-3-11 01:37
avr不知不觉都落后这么多了,stm32实在太强大了

小工程、极小批量我还是喜欢用AVR,毕竟现成的电路和代码,关键还耐操,最短时间挣到最多的钱才是王道。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-4-27 05:14 , Processed in 0.140401 second(s), 14 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

快速回复 返回顶部 返回列表