реклама на сайте
подробности

 
 
> Проблема С PWM на LPC1751, ARM, PWM
Илья_
сообщение Sep 13 2013, 10:05
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 18-10-07
Пользователь №: 31 472



Добрый день господа форумчане.
Сталкивался ли кто нибудь с такой проблемой, что при формировании ШИM-сигнала при помощи модуля PWM в сигнале возникают периоды когда выход остается в высоком уровне ?

Прикрепленное изображение


Код для работы с модулем PWM у меня такой:

CODE
/*
* ch3_8_hal.c
*
* Created on: 10.03.2012
* Author: Илья
*/

#include "LPC17xx.h"

#define MR0_INT (1 << 0)
#define MR1_INT (1 << 1)
#define MR2_INT (1 << 2)
#define MR3_INT (1 << 3)
#define MR4_INT (1 << 8)
#define MR5_INT (1 << 9)
#define MR6_INT (1 << 10)

#define TCR_CNT_EN 0x00000001
#define TCR_RESET 0x00000002
#define TCR_PWM_EN 0x00000008

#define PWMMR0I (1 << 0)
#define PWMMR0R (1 << 1)
#define PWMMR0S (1 << 2)
#define PWMMR1I (1 << 3)
#define PWMMR1R (1 << 4)
#define PWMMR1S (1 << 5)
#define PWMMR2I (1 << 6)
#define PWMMR2R (1 << 7)
#define PWMMR2S (1 << 8)
#define PWMMR3I (1 << 9)
#define PWMMR3R (1 << 10)
#define PWMMR3S (1 << 11)
#define PWMMR4I (1 << 12)
#define PWMMR4R (1 << 13)
#define PWMMR4S (1 << 14)
#define PWMMR5I (1 << 15)
#define PWMMR5R (1 << 16)
#define PWMMR5S (1 << 17)
#define PWMMR6I (1 << 18)
#define PWMMR6R (1 << 19)
#define PWMMR6S (1 << 20)

#define PWMSEL2 (1 << 2)
#define PWMSEL3 (1 << 3)
#define PWMSEL4 (1 << 4)
#define PWMSEL5 (1 << 5)
#define PWMSEL6 (1 << 6)
#define PWMENA1 (1 << 9)
#define PWMENA2 (1 << 10)
#define PWMENA3 (1 << 11)
#define PWMENA4 (1 << 12)
#define PWMENA5 (1 << 13)
#define PWMENA6 (1 << 14)

#define LER0_EN (1 << 0)
#define LER1_EN (1 << 1)
#define LER2_EN (1 << 2)
#define LER3_EN (1 << 3)
#define LER4_EN (1 << 4)
#define LER5_EN (1 << 5)
#define LER6_EN (1 << 6)


#define ACTIVE_TAKT_1_CH3 2
#define ACTIVE_TAKT_2_CH3 12

#define ACTIVE_TAKT_1_CH4 2
#define ACTIVE_TAKT_2_CH4 12

#define ACTIVE_TAKT_1_CH5 3
#define ACTIVE_TAKT_2_CH5 11

#define ACTIVE_TAKT_1_CH6 3
#define ACTIVE_TAKT_2_CH6 11

#define ACTIVE_TAKT_1_CH7 4
#define ACTIVE_TAKT_2_CH7 12

#define ACTIVE_TAKT_1_CH8 4
#define ACTIVE_TAKT_2_CH8 12

static uint_fast8_t current_takt;

//-----------------------------------------------------------------------------
static void pwm_ch3_8_irq_hw (void)
{
volatile uint32_t regVal;
volatile uint32_t load_value = 0ul;


//__disable_fault_irq();
//__disable_irq();

regVal = LPC_PWM1->IR;
LPC_PWM1->IR = regVal; /* clear interrupt flag on match 0 */

if( regVal & MR0_INT )
{
if(LPC_PWM1->MR1)
{
if(
current_takt == ACTIVE_TAKT_1_CH3 ||
current_takt == ACTIVE_TAKT_2_CH3
)
{
load_value |= 0x00008000;
}
}

if(LPC_PWM1->MR2)
{
if(
current_takt == ACTIVE_TAKT_1_CH4 ||
current_takt == ACTIVE_TAKT_2_CH4
)
{
load_value |= 0x00010000;
}
}

if(LPC_PWM1->MR3)
{
if(
current_takt == ACTIVE_TAKT_1_CH5 ||
current_takt == ACTIVE_TAKT_2_CH5
)
{
load_value |= 0x00020000;
}
}

if(LPC_PWM1->MR4)
{
if(
current_takt == ACTIVE_TAKT_1_CH6 ||
current_takt == ACTIVE_TAKT_2_CH6
)
{
load_value |= 0x00040000;
}
}

if(LPC_PWM1->MR5)
{
if(
current_takt == ACTIVE_TAKT_1_CH7 ||
current_takt == ACTIVE_TAKT_2_CH7
)
{
load_value |= 0x40000000;
}
}

LPC_GPIO0->FIOSET = load_value; /* swich on */

if(LPC_PWM1->MR6)
{
if(
current_takt == ACTIVE_TAKT_1_CH8 ||
current_takt == ACTIVE_TAKT_2_CH8
)
{
LPC_GPIO1->FIOSET = 0x00008000;
}
}

//return;
}

load_value = 0ul; // Обнуляю переменную перед тем как использовать ее еще раз

if( regVal & MR1_INT )
load_value |= 0x00008000;

if( regVal & MR2_INT )
load_value |= 0x00010000;

if( regVal & MR3_INT )
load_value |= 0x00020000;

if( regVal & MR4_INT )
load_value |= 0x00040000;

if( regVal & MR5_INT )
load_value |= 0x40000000;

LPC_GPIO0->FIOCLR = load_value;

if( regVal & MR6_INT )
LPC_GPIO1->FIOCLR = 0x00008000;

// __enable_fault_irq();
// __enable_irq();
}




//-----------------------------------------------------------------------------
static void ch3_8_init_hw(void)
{
// Out_3, Out_4
LPC_PINCON->PINSEL0 &= 0x3FFFFFFF; // P0.15 as GPIO port
LPC_PINCON->PINSEL1 &= 0xCFFFFFC0; // Настрою P0.16...P0.18, P0.30 как GPIO
// и обнулю выходы
LPC_PINCON->PINSEL2 &= 0x3FFFFFFF; // P1.15 as GPIO port

LPC_PINCON->PINMODE0 &= 0x3FFFFFFF; // not pull-... mode
LPC_PINCON->PINMODE0 |= 0x80000000;
LPC_PINCON->PINMODE1 &= 0xCFFFFFC0; // not pull-... mode
LPC_PINCON->PINMODE1 |= 0x2F00002A;
LPC_PINCON->PINMODE2 &= 0x3FFFFFFF; // not pull-... mode
LPC_PINCON->PINMODE2 |= 0x80000000;

LPC_PINCON->PINMODE_OD0 &= 0xBFF87FFF;
LPC_PINCON->PINMODE_OD1 &= 0xFFFF7FFF;

LPC_GPIO0->FIODIR |= 0x40078000;
LPC_GPIO0->FIOCLR = 0x40078000;

LPC_GPIO1->FIODIR |= 0x00008000;
LPC_GPIO1->FIOCLR = 0x00008000;

// Следующие две строчки должны быть одикаковы для всех каналов PWM
LPC_PWM1->TCR = TCR_CNT_EN | TCR_RESET; /* Counter enable, Counter Reset*/
LPC_PWM1->PR = 0ul; /* count frequency:Fpclk */

LPC_PWM1->MR0 = 0ul;
LPC_PWM1->MR1 = 0ul;
LPC_PWM1->MR2 = 0ul;
LPC_PWM1->MR3 = 0ul;
LPC_PWM1->MR4 = 0ul;
LPC_PWM1->MR5 = 0ul;
LPC_PWM1->MR6 = 0ul;

LPC_PWM1->PCR = 0ul;
LPC_PWM1->MCR = PWMMR0R | PWMMR0I | PWMMR1I | PWMMR2I |
PWMMR3I | PWMMR4I | PWMMR5I | PWMMR6I;
NVIC_SetPriority(PWM1_IRQn,0);
NVIC_EnableIRQ(PWM1_IRQn);


}



//-----------------------------------------------------------------------------
static void ch3_8_pwm_start_hw(void)
{
/* All single edge, all enable */
// LPC_PWM1->TCR &= ~(TCR_RESET);
// LPC_PWM1->TCR |= TCR_PWM_EN;

LPC_PWM1->TCR = 0x00000009; /* counter enable, ResetdisablePWM enable */
}


//-----------------------------------------------------------------------------
static void ch3_8_pwm_stop_hw(void)
{
LPC_PWM1->MR0 = 0ul; /* set PWM cycle */

/* set PWM offsets */
LPC_PWM1->MR1 = 0ul;
LPC_PWM1->MR2 = 0ul;
LPC_PWM1->MR3 = 0ul;
LPC_PWM1->MR4 = 0ul;
LPC_PWM1->MR5 = 0ul;
LPC_PWM1->MR6 = 0ul;

LPC_PWM1->LER |= 0x0000007F;

LPC_PWM1->TCR |= TCR_RESET; /* Counter Reset */

LPC_GPIO0->FIOCLR = 0x40078000;
LPC_GPIO1->FIOCLR = 0x00008000;
}


//-----------------------------------------------------------------------------
static void ch3_8_pwm_set_freq_offset_hw(uint32_t cycle, uint_fast8_t takt, uint32_t* p_offset_arr)
{
uint32_t old_MR0;

current_takt = takt;

if(cycle == 0ul)
{
ch3_8_pwm_stop_hw();
old_MR0 = 0;
return;
}

old_MR0 = LPC_PWM1->MR0;
LPC_PWM1->MR0 = cycle; /* set PWM cycle */

/* The LER will be cleared when the Match 0 takes place, in order to
load and execute the new value of match registers, all the PWMLERs need to
reloaded. all PWM latch enabled */

LPC_PWM1->MR1 = *p_offset_arr; /* set PWM offsets */
LPC_PWM1->MR2 = *(p_offset_arr+1);
LPC_PWM1->MR3 = *(p_offset_arr+2);
LPC_PWM1->MR4 = *(p_offset_arr+3);
LPC_PWM1->MR5 = *(p_offset_arr+4);
LPC_PWM1->MR6 = *(p_offset_arr+5);

LPC_PWM1->LER |= 0x0000007F;

if(old_MR0 == 0ul) // См. data sheet значение регистра после сброса
ch3_8_pwm_start_hw();

}


У меня шесть выходов ШИМа работающих на одной частоте 80...200 Гц. У них разный DC.
Управление периодом и DC сразу всех каналов ШИМа я осуществляю через функцию ch3_8_pwm_set_freq_offset_hw().

Из нее видно, что я сначала изменяю период ШИМа (регистр LPC_PWM1->MR0), затем меняю DC всех шести каналов,
затем устанавливаю биты в регистре LPC_PWM1->LER, разрешая при следующем переполнении таймера модуля PWM
переписать новые значения MR0... MR6 в теневые регистры модуля PWM.

И обычно так и происходит. Но вот иногда происходит такая картина как первом рисунке. Иногда - это примерно один раз в 20 минут и случайно на одном из шести каналов. Сейчас удалось поймать на первом(MR1).

Так кажется как будто не пришло прерывание от совпадения регистра MR1 и счетного регистра таймера PWM?
Или как будто в теневой регистр MR1 записалось значение больше чем MR0?
А может быть надо таймер PWM останавливать когда я обновляю регистры MR0....MR6, но в pdf ничего такого не написано?
Не знаю что и думать.....

Сообщение отредактировал Илья_ - Sep 13 2013, 14:12
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!

Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 22:40
Рейтинг@Mail.ru


Страница сгенерированна за 0.01334 секунд с 7
ELECTRONIX ©2004-2016