通用LED闪烁代码模块(也可实现软件PWM)

 仅提供参考文件:

1、需要修改gpio引脚

2、需要根据平台实现软件定时器接口,启动,停止,回调,三个API。

3、根据平台优化相关错误即可

/*
 * pwm_drv.c
 *
 *  Created on: 2021年3月3日
 *      Author: Administrator
 */
#include "pwm_drv.h"
#include "appled.h"


enum {
  PWM_LED = 0x00,
  PWM_CHANNELS = 0x01
};


UserPwm_t userPwm[PWM_CHANNELS];

//定时器定义
EmberEventControl emberAfPluginBulbPwmDriverBlinkEventControl;


enum {

  PWM_OUTPUT_ON            = 0x00,
  PWM_OUTPUT_OFF           = 0x01,
  PWM_BLINKING_ON       = 0x02,
  PWM_BLINKING_OFF      = 0x03,
  PWM_BLINK_PATTERN     = 0x04,

};



static void pwmOutputOn(uint16_t time, UserPwm_t *p)
{
  p->turnOn();
  p->state = PWM_OUTPUT_ON;

  if (time > 0) {
    emberEventControlSetDelayMS(*(p->eventControl),
                                ((uint32_t) time) * SECONDS_TO_MILLISECONDS);
  } else {
    emberEventControlSetInactive(*(p->eventControl));
  }
}

static void pwmOutputOff(uint16_t time, UserPwm_t *p)
{
  p->turnOff();
  p->state = PWM_OUTPUT_OFF;

  if (time > 0) {
    emberEventControlSetDelayMS(*(p->eventControl),
                                ((uint32_t) time) * SECONDS_TO_MILLISECONDS);
  } else {
    emberEventControlSetInactive(*(p->eventControl));
  }
}

static void pwmBlink(uint16_t count, uint16_t blinkTime, UserPwm_t *p)
{
  p->blinkTime = blinkTime;

  p->turnOff();
  p->state = PWM_BLINKING_OFF;
  emberEventControlSetDelayMS(*(p->eventControl),
                              p->blinkTime);
  p->count = count;
}


static void pwmTurnHigh(void)
{

	HalSetledOnOff(BSP_LED1_PORT,BSP_LED1_PIN,true);

}

static void pwmTurnLow(void)
{
	HalSetledOnOff(BSP_LED1_PORT,BSP_LED1_PIN,false);
}


static void pwmRunStop(void)
{

}


static void pwmRunStart(void)
{

}


// For example, if we wished to create an SOS pattern, we would
// program the following array:
// pattern[20] = {500, 100, 500, 100, 500, 100, 100, 100, 100, 100, 100, 100,
//                500, 100, 500, 100, 500, 100};
// Where the gpio would be on in a sequences of 500 and 100 mS intervals, and
// the gpio would be off for 100 mS in between the on intervals.
static void pwmRunPattern(uint16_t    count,
                         uint16_t    length,
                         uint16_t   *pattern,
                         UserPwm_t *p)
{
  uint16_t i;

  if (length < 2) {
    return;
  }

  p->turnOn();

  p->state = PWM_BLINK_PATTERN;

  if (length > PWM_PATTERN_MAX_LENGTH) {
    length = PWM_PATTERN_MAX_LENGTH;
  }

  p->patternLength = length;
  p->count = count;

  for (i = 0; i < p->patternLength; i++) {
    p->pattern[i] = pattern[i];
  }

  emberEventControlSetDelayMS(*(p->eventControl),
                              p->pattern[0]);

  p->patternIndex = 1;
}




void pwmeventHandler(UserPwm_t *p)
{
  emberEventControlSetInactive(*(p->eventControl));
  switch (p->state) {
    case PWM_OUTPUT_ON:
      p->turnOff();
      p->stop();
      break;

    case PWM_OUTPUT_OFF:
      p->turnOn();
      p->stop();
      break;

    case PWM_BLINKING_ON:
      p->turnOff();
      if (p->count == 0) {
        p->state = PWM_OUTPUT_OFF;
        p->stop();

        break;
      }

      if (p->count != PWM_DRIVER_RUN_FOREVER) {
        p->count--;
      }
      if (p->count > 0) {
        p->state = PWM_BLINKING_OFF;
        emberEventControlSetDelayMS(*(p->eventControl),
                                    p->blinkTime);
      } else {
        p->state = PWM_OUTPUT_OFF;
        p->stop();
      }

      break;
    case PWM_BLINKING_OFF:
      p->turnOn();
      p->state = PWM_BLINKING_ON;
      emberEventControlSetDelayMS(*(p->eventControl),
                                  p->blinkTime);
      break;


    case PWM_BLINK_PATTERN:
      if (p->count == 0) {
        p->turnOff();

        p->state = PWM_OUTPUT_OFF;
        p->stop();

        break;
      }

      if (p->patternIndex % 2 == 1) {
        p->turnOff();
      } else {
        p->turnOn();
      }

      emberEventControlSetDelayMS(*(p->eventControl),
                                  p->pattern[p->patternIndex]);

      p->patternIndex++;

      if (p->patternIndex >= p->patternLength) {
        p->patternIndex = 0;

        if (p->count != PWM_DRIVER_RUN_FOREVER) {
          p->count--;
        }
      }
      break;
    default:
      break;
  }
}



void PwmDriverRunPattern(uint16_t  count,
                                     uint16_t  length,
                                     uint16_t *pattern)
{
  pwmRunPattern(count, length, pattern, &(userPwm[PWM_LED]));
}

void PwmDriverBlink(uint16_t count, uint16_t blinkTime)
{
   pwmBlink(count, blinkTime, &(userPwm[PWM_LED]));
}

void PwmDriverOutputOn(uint16_t time)
{
	pwmOutputOn(time, &(userPwm[PWM_LED]));
}


void PwmDriverOutputOff(uint16_t time)
{
	pwmOutputOff(time, &(userPwm[PWM_LED]));
}



// ******** APIs and Event Functions *************
void emberAfPluginBulbPwmDriverBlinkEventHandler(void)
{
  pwmeventHandler(&(userPwm[PWM_LED]));
}



void PwmDriverInit(void)
{
  userPwm[PWM_LED].turnOn  = pwmTurnHigh;
  userPwm[PWM_LED].turnOff = pwmTurnLow;
  userPwm[PWM_LED].start   = pwmRunStart;
  userPwm[PWM_LED].stop    = pwmRunStop;
  userPwm[PWM_LED].eventControl = &(emberAfPluginBulbPwmDriverBlinkEventControl);

}


// sequence   on -> off ->on -> off ->...

void testpwm(void)
{
	  PwmDriverInit();

	  uint16_t pattern[18] = {500, 100, 500, 100, 500, 100, 100, 100, 100, 100, 100, 100,500, 100, 500, 100, 500, 100};
	  PwmDriverRunPattern(2,sizeof(pattern),pattern);

	  //PwmDriverBlink(10,500);

	  //PwmDriverOutputOff(2000);

	  //PwmDriverOutputOn(2000);
}

/*
 * pwm_drv.h
 *
 *  Created on: 2021年3月3日
 *      Author: Administrator
 */

#ifndef EXTERNAL_COPIED_FILES_PWM_DRV_H_
#define EXTERNAL_COPIED_FILES_PWM_DRV_H_

#include <stdio.h>
#include "app/framework/include/af.h"



#define  SECONDS_TO_MILLISECONDS   (1)
#define  PWM_PATTERN_MAX_LENGTH    (20)
#define  PWM_DRIVER_RUN_FOREVER    (0xffff)

typedef struct {
  uint8_t state;
  uint16_t count;
  uint16_t blinkTime;

  uint16_t pattern[PWM_PATTERN_MAX_LENGTH];
  uint16_t patternLength;
  uint16_t patternIndex;

  void (*turnOn)(void);
  void (*turnOff)(void);
  void (*start)(void);
  void (*stop)(void);

  EmberEventControl *eventControl;
} UserPwm_t;


void PwmDriverInit(void);
void PwmDriverRunPattern(uint16_t  count,
						 uint16_t  length,
                         uint16_t *pattern);
void PwmDriverBlink(uint16_t count, uint16_t blinkTime);

void PwmDriverOutputOn(uint16_t time);

void PwmDriverOutputOff(uint16_t time);


void testpwm(void);

#endif /* EXTERNAL_COPIED_FILES_PWM_DRV_H_ */

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个基于DSP的PWM控制LED闪烁的示例代码(仅作参考,实际代码可能因DSP平台而异): ```c #include <stdio.h> #include <stdint.h> // 定义定时器和计数器的寄存器地址 #define TIMER_BASE_ADDR 0x1000 #define COUNTER_BASE_ADDR 0x2000 // 定义LED GPIO引脚的寄存器地址 #define LED_GPIO_BASE_ADDR 0x3000 // 定义PWM参数 #define PWM_FREQUENCY 1000 // PWM频率为1kHz #define PWM_DUTY_CYCLE 50 // PWM占空比为50% // 设定定时器和计数器的初始值和上限值 uint16_t timer_init_value = 0; uint16_t timer_limit_value = 0; uint16_t counter_init_value = 0; uint16_t counter_limit_value = 0; // 初始化PWM控制 void pwm_init() { // 配置定时器和计数器 *(volatile uint16_t*)(TIMER_BASE_ADDR + 0x00) = timer_init_value; *(volatile uint16_t*)(TIMER_BASE_ADDR + 0x04) = timer_limit_value; *(volatile uint16_t*)(COUNTER_BASE_ADDR + 0x00) = counter_init_value; *(volatile uint16_t*)(COUNTER_BASE_ADDR + 0x04) = counter_limit_value; // 配置LED GPIO引脚为输出模式 *(volatile uint8_t*)(LED_GPIO_BASE_ADDR + 0x00) |= (1 << 1); } // 更新PWM参数 void pwm_update(uint16_t duty_cycle) { // 更新计数器的上限值 counter_limit_value = (timer_limit_value * duty_cycle) / 100; *(volatile uint16_t*)(COUNTER_BASE_ADDR + 0x04) = counter_limit_value; } // 控制LED闪烁 void led_blink() { // 检查计数器是否小于阈值,控制LED状态 while (*(volatile uint16_t*)(COUNTER_BASE_ADDR + 0x00) < counter_limit_value) { *(volatile uint8_t*)(LED_GPIO_BASE_ADDR + 0x01) |= (1 << 1); // LED亮起 } *(volatile uint8_t*)(LED_GPIO_BASE_ADDR + 0x01) &= ~(1 << 1); // LED熄灭 } int main() { // 初始化PWM控制 pwm_init(); // 计算定时器和计数器的初始值和上限值 timer_init_value = (uint16_t)(1e6 / PWM_FREQUENCY); timer_limit_value = (uint16_t)(timer_init_value / 2); counter_init_value = 0; counter_limit_value = (timer_limit_value * PWM_DUTY_CYCLE) / 100; // 更新PWM参数 pwm_update(PWM_DUTY_CYCLE); // 控制LED闪烁 while (1) { led_blink(); } return 0; } ``` 请注意,上述代码仅是一个示例,具体的实现可能因DSP平台而异。你需要根据你所使用的DSP芯片的文档和开发工具来进行相应的配置和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值