你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

我的迷你STM32F030核心板及三种PWM实现呼吸灯的方法

[复制链接]
网络孤客 发布时间:2020-3-10 15:55
不是所有芯片都有开发板,官方会比较齐全,但价格也上来了。
虽然打板比较便宜,但前期研究电路不确定。
还是充分利用STM32外围原件简单的优势,自己搭建核心板。
材料:芯片,SSOP20转DIP20转接板
微信图片_20200310121033.jpg

焊接好
微信图片_20200310110526.jpg
外围电路图,只做了上电复位电路和boot0电路
电路图.jpg
搭好电路后测试,够迷你吧。
微信图片_20200310110554.jpg

不想只点个灯,还是玩呼吸灯吧!
在CUBEMX中设置时钟48Mhz,TIM3的Channel1为“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,不够用。
思路是当计数器达到预置比较值时产生一个中断,设置IO口,当达到重置值时再产生一个中断,反转IO口输出。
在CUBEMX中设置时钟48Mhz,TIM3的Channel1为“PWM Generation No Output”,把IO口还原出来。
我选择了2个IO口,分别定义为LED和LED2,为了更好效果,程序中两灯状态刚好相反

为了程序简约,我在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没输出,
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
  LED_ON;
  LED2_OFF;
}


请各路大侠指点










1 收藏 2 评论9 发布时间:2020-3-10 15:55

举报

9个回答
Royliang 回答时间:2020-3-10 17:18:13
不错
jeffhe1 回答时间:2020-3-11 09:00:44
算不錯 , 但真正呼吸燈應該是有曲線的 , 應該不是固定時間 , 加減固定的值
网络孤客 回答时间:2020-3-11 09:02:42
jeffhe1 发表于 2020-3-11 09:00
算不錯 , 但真正呼吸燈應該是有曲線的 , 應該不是固定時間 , 加減固定的值  ...

的确,搞个数组或算法函数就可以实现了。
主要是中断问题,HAL库很少有介绍,
特别是回调函数的与中断对应关系,我不太懂,也不知哪里能查到。估计和我一样的也有不少,所以把摸索到的写出来而已。
mmuuss586 回答时间:2020-3-11 10:13:21

不错
zcljll 回答时间:2020-3-13 10:03:01
不错不错
jason150257 回答时间:2020-3-15 17:32:41
学习了
Glenxu 回答时间:2020-3-16 12:09:51
肥肠好!学习了!
Glenxu 回答时间:2021-2-25 10:50:43
思路很灵活,不错。         以下语句中后面依据是无效语句:

HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1);                  //开启PWM中断
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);                     //开启PWM
网络孤客 回答时间:2021-2-25 12:58:32
glenxu 发表于 2021-2-25 10:50
思路很灵活,不错。         以下语句中后面依据是无效语句:

HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_ ...

时间有点久了,忘了这贴了。
我找时间再试试,当时一直不能没输出,也是摸索了很久,各种组合试了。后面没进一步优化。

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版