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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Замечал ли кто-то странности с PWM на lpc2103 ?, непонятное поведение регистра сравнения в PWM режиме
avva
сообщение Jul 7 2008, 14:46
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 15-02-07
Из: Москва
Пользователь №: 25 386



Уважаемый ALL, может быть кто-то сталкивался, помогите в какую сторону копнуть...

IAR 5.11,
IAR Elf Linker for ARM 5.11.0.50622 (5.11.0.50622)
IAR C/C++ Compiler for ARM 5.11.0.20622 (5.11.0.20622)


Вывожу с помощью PWM синус по 800 точкам. таблица синуса объявлена полуволной!!! из констант
unsigned int const sin1024[400]={\ ... }; константы в сегменте флэш-памяти lpc2103.
Задача вывода PWM тривиальная - по прерыванию 3-го канала (период) обновляю данные регистра сравнения T0MR0. после RC цепочки на ноге МАТ0.0 смотрим синус осциллографом.

Имею абсолютно непонятную ситуацию - "задир" (то есть T0MR0 имеет сильно неверное значение) (иногда два "задира", а иногда - ни одного) на синусе, причем этот задир только на одной (левой "верхней" то бишь значенияT0MR0 должны лежать в диапазоне [0 .. 1/2Period ] ) полуволне, и самое поразительное, что в зависимости от положения звёзд на рабочем проекте "задир(ы)" то проявляются, то не проявляется. На тестовом проекте задир всегда постоянен и всегда один.


Таблица синуса правильная, в пошаговом режиме проблем не возникает, на кристалле в головном проекте крутится ещё несколько прерываний, они не являются причиной (иногда синус абсолютно чистый, а иногда именно в данном месте то один, то два "задира").


Проблема проявляется даже на прилагаемом тестовом проекте (должен заработать у каждого под иар5.11 ). кварц 12мГц, обычная отладка от Олимекса с 2103.

Прошу оказать конструктивную помощь, высказать замечание или кинуть в меня соответствующей ссылкой.
Умозрительные предположения прошу делать аккуратно, ибо пока все умозрительные предположения стукнулись головой о реальный камень...

ПРИЛАГАЕМЫЙ ПРОЕКТ Прикрепленный файл  test_pwm_issue_lpc2103.rar ( 89.07 килобайт ) Кол-во скачиваний: 114


Сообщение отредактировал avva - Jul 7 2008, 14:54


--------------------
С уважением,
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jul 7 2008, 15:41
Сообщение #2


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Могу сказать, что делал почти точно так же на LPC2132 и всё работало чудесно. Только перезагрузку MACH регистра делал по прерыванию 0-ого канала, который задаёт период PWM, то бишь обнуляет счётчик. В возникающем при этом прерывании обновлял PWMMR1 и стробировал PWMLER, а затем сразу же выходил из прерывания.

Кстати, таймер отличается от PWM тем, что у него нет защёлок на MACH регистрах (регистра PWMLER). Может в этом косяк.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Alex03
сообщение Jul 8 2008, 04:08
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034



Както странно, у Вас PWM_period_val и период таймера (задающий частоту ШИМ) и амплитуда синуса....

Вот тут:
Код
  if (i>399){
// it seems problem in this part of
    val=( (PWM_period_val-( (PWM_period_val*usin[i-400] -1 )>>10))>>1 );
  }else{
    val=( ((PWM_period_val+((PWM_period_val*usin[i] -1 )>>10))>>1));  
  }

зачем "-1" ? Искажений добавляете? Впрочем возможно что в вашем случае они не появятся (при перермножении 375 на табличные значения наверняка не будет произведения где младшие 10 бит нулевые).
Может хотели ((PWM_period_val-1)*usin[i]) ?
Да и вообще весь этот код упростить можно.

И почему у Вас в таблице полуволны синуса первый элемент 3 а не 0? А если заменить на 0 то как раз та самая "-1" то и вылезет. smile.gif


Вот эта конструкция
Код
i = (i != 799) ? ++i : 0;
тоже достойна похвалы... sad.gif
Go to the top of the page
 
+Quote Post
avva
сообщение Jul 8 2008, 07:08
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 15-02-07
Из: Москва
Пользователь №: 25 386



Цитата
Както странно, у Вас PWM_period_val и период таймера (задающий частоту ШИМ) и амплитуда синуса....
...
зачем "-1" ? Искажений добавляете? Впрочем возможно что в вашем случае они не появятся (при перермножении 375 на табличные значения наверняка не будет произведения где младшие 10 бит нулевые).
Может хотели ((PWM_period_val-1)*usin[i]) ?
Да и вообще весь этот код упростить можно.


Alex03, проблема абсолютно в другом.... (я согласен с вами, что "-1" это лишнее, но это всё-равно. таблица полу-синуса хоть с 10 может начинаться - она на 0х3FF отнормирована, так что там всё-равно.). проблема в том, что каким-то непонятным образом в tmrmr0 !однократно! попадает!? значение больше или равное периоду pwm, что вызывает установку соответсвтующей ноги в 0 на период шима. как такое происходит - ума не приложу.
пока все догадки и эксперименты были из области фантастики, по-этому я решил обратиться к многоуважаемому сообществу.

Цитата
И почему у Вас в таблице полуволны синуса первый элемент 3 а не 0? А если заменить на 0 то как раз та самая "-1" то и вылезет. smile.gif
Вот эта конструкция
Код
i = (i != 799) ? ++i : 0;
тоже достойна похвалы... sad.gif

это стандартная конструкция языка ANSI C, думаю это вопрос не принципиальный )


Цитата(GetSmart @ Jul 7 2008, 19:41) *
Могу сказать, что делал почти точно так же на LPC2132 и всё работало чудесно. Только перезагрузку MACH регистра делал по прерыванию 0-ого канала, который задаёт период PWM, то бишь обнуляет счётчик. В возникающем при этом прерывании обновлял PWMMR1 и стробировал PWMLER, а затем сразу же выходил из прерывания.

Кстати, таймер отличается от PWM тем, что у него нет защёлок на MACH регистрах (регистра PWMLER). Может в этом косяк.


я использую именно описанный в доке режим PWM, канал 3 - задаёт период PWM, а каналы 0 1 и 2 в рабочем проекте - разные PWM с одним периодом (канал 3)

собственно в данном случае проблему надо глазами видеть. Понимаете, я бы понял, если бы проблема проявлялась на "пике" какого-то канала, тогда можно было бы говорить о переполнении и всякой такой простой ерунде, однако "задир" проявляется - фото (качество не очень, синус - идеальный но имеет "задир")

Буду благодарен за умную мысль по теме.

ФОТО "ЗАДИРА"
 Р В˜Р В·Р С•бражение уменьшено
Прикрепленное изображение
(53.27 килобайт)


--------------------
С уважением,
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jul 8 2008, 08:32
Сообщение #5


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Вобщем так. Без LER регистра будет наблюдаться следующий эффект. При возникновении прерывания (обнуления таймера) таймер начинает тикать с нуля со старым действующим MR (пока он не перезагрузится). В этот момент начинает выполняться обработчик. Дойдя до места в котором программа будет готова перезагрузить регистр MR, если при этом таймер ещё не дошёл до старого MR и уже прошёл новый MR, то MATCH-пин никогда не обнулится, т.к. он обнуляется по совпадению значений. Этот эффект возникает в местах, когда значение MR относительно мало, то есть недалеко от пика синусоиды. Ещё один косяк возникает с противоположной стороны этого же пика синусоиды - там происходит "выпадение" одного из значений на синусоиде, когда происходит "обгон" старых значений MR новыми.

Для облегчения жизни программистам в настоящем PWM ввели регистр PWMLER.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
avva
сообщение Jul 8 2008, 09:16
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 15-02-07
Из: Москва
Пользователь №: 25 386



Уважаемый GetSmart, похоже, что вы оказались правы или где-то очень очень рядом около того.

СПАСИБО.


Во всяком случае, патч вот этих строчек в тестовом проекте привёл к желаемому результату, жаль только, что форма синуса изза остановки таймера периода в момент прерывания и перезагрузки регистров сравнения, немножечко будет искажена. думаю, искажением формы можно пренебречь

100+ T0TCR = 0x01; //перезапуск таймера после окончания прерывания таймера

218 T0MCR = 0x0E00; // добавление STOP в процедуре инита периода шима таймера0 канал3


--------------------
С уважением,
Go to the top of the page
 
+Quote Post
Alex03
сообщение Jul 8 2008, 09:22
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034



Цитата(avva @ Jul 8 2008, 13:08) *
Код
i = (i != 799) ? ++i : 0;

это стандартная конструкция языка ANSI C, думаю это вопрос не принципиальный )

ИМХО это из области
Код
i += i++ + ++i;

Не рекомендовал бы так писать. К тому же если объявить i как volatile то переменная будет прописываться в памяти дважды (да и в некоторых других случаях, как то debug, тоже), хоть и одним значением.
Лучше/правильнее
Код
i = (i != 799) ? i+1 : 0;
или уж
Код
if(i != 799)
    ++i;
else
    i = 0;


Впрочем, ДА, к теме топика не имеет отношения.

Цитата(avva @ Jul 8 2008, 13:08) *
Понимаете, я бы понял, если бы проблема проявлялась на "пике" какого-то канала, тогда можно было бы говорить о переполнении и всякой такой простой ерунде, однако "задир" проявляется - фото

RC-цепочка двигает фазу, так что возможно что на фото и есть пик синусоиды...
Go to the top of the page
 
+Quote Post
avva
сообщение Jul 8 2008, 09:24
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 15-02-07
Из: Москва
Пользователь №: 25 386



Alex03, спасибо, я учту в будущем. (серьёзно).

Цитата
RC-цепочка двигает фазу, так что возможно что на фото и есть пик синусоиды...


Фигню полную написали вы сейчас насчёт возможного пика.

Сообщение отредактировал avva - Jul 8 2008, 09:27


--------------------
С уважением,
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jul 8 2008, 09:36
Сообщение #9


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(avva)
Уважаемый GetSmart, похоже, что вы оказались правы или где-то очень очень рядом около того.
Я оказался прав на 100% smile.gif
Только для обхода этого косяка не обязательно останавливать таймер. Достаточно уменьшить амплитуду синусоиды на несколько процентов чтобы в регистр MR не записывались очень маленькие значения. Например в диапазоне от 25 до 375. Минимально допустимое значение для MR зависит от скорости реакции на прерывание. Если у этого прерывания будет не самый высокий приоритет или будут возникать другие прерывания недопускающие вложенность, то будут глюки.

Сообщение отредактировал GetSmart - Jul 8 2008, 09:40


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Alex03
сообщение Jul 8 2008, 10:01
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034



Цитата(avva @ Jul 8 2008, 15:24) *
Alex03, спасибо, я учту в будущем. (серьёзно).

Так и я серьёзно, стоит ++ переставить и уже всё интересней smile.gif
Код
int i = 10;
i = (i != 799) ? i++ : 0;
MSVC 2003 - результат 10!


Цитата
Фигню полную написали вы сейчас насчёт возможного пика.
Я не знаю Ваших частот и номиналов, но чем больше R и С тем больше сдвиг фазы стремится к 90 градусов (с сильным уменьшением амплитуды). И тем правильнее форма сигнала.
Хотя судя по тому что "задир" такой "резкий" номиналы у Вас довольно небольшие.


Цитата(GetSmart @ Jul 8 2008, 15:36) *
...
Только для обхода этого косяка не обязательно останавливать таймер. Достаточно уменьшить амплитуду синусоиды на несколько процентов чтобы в регистр MR не записывались очень маленькие значения. Например в диапазоне от 25 до 375. Минимально допустимое значение для MR зависит от скорости реакции на прерывание. Если у этого прерывания будет не самый высокий приоритет или будут возникать другие прерывания недопускающие вложенность, то будут глюки.

+1

А скорость реакции увеличить легко выкинув полонстью
Код
__irq __arm void irq_handler (void)
{
void (*interrupt_function)();
unsigned int vector;

  vector = VICVectAddr;     // Get interrupt vector.
  interrupt_function = (void(*)())vector;
  if(interrupt_function != NULL){
    interrupt_function();  // Call vectored interrupt function.
  }
  
  VICVectAddr = 0;        // Clear interrupt in VIC.
  return;
}

Достаточно
Код
ldr pc, [pc, #-0xFF0]
в области векторов прерываний (по адресу 0x00000018)
И timer0_handler() объявить с __irq и с VICVectAddr = 0; в конце.
Зачем проверки, Вы сами себе не доверяете?

Ну и задержать можно всё на период
Код
__irq __arm void timer0_handler(void)
{
  static unsigned int i;
  static unsigned int val = ХХХ;

  T0MR0 = val;

  // Вычисление val для след. прерывания.


  VICVectAddr = 0;        // Clear interrupt in VIC.
}
Go to the top of the page
 
+Quote Post
cebotor
сообщение Jul 8 2008, 10:26
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 6-04-07
Из: Бронницы
Пользователь №: 26 809



Цитата(avva @ Jul 8 2008, 13:16) *
100+ T0TCR = 0x01; //перезапуск таймера после окончания прерывания таймера

причина засора прояснилась, однако я совершенно не согласен что можно принебрегать формой синусоиды , вводя такие погрешности уважаемый АВВА вы из чистой синусоиды на спектре получите
фиг знает что.

Вопрос - почему нельзя перегружать значение по соответствующему прерыванию (для нулевого канала по прерыванию матча нулевого канала )- будет все хорошо и вперед и назад ? smile.gif


--------------------
если еррата пуста - это не хорошо а плохо
Go to the top of the page
 
+Quote Post
avva
сообщение Jul 8 2008, 10:34
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 15-02-07
Из: Москва
Пользователь №: 25 386



Цитата(GetSmart @ Jul 8 2008, 13:36) *
Я оказался прав на 100% smile.gif
Только для обхода этого косяка не обязательно останавливать таймер. Достаточно уменьшить амплитуду синусоиды на несколько процентов чтобы в регистр MR не записывались очень маленькие значения. Например в диапазоне от 25 до 375. Минимально допустимое значение для MR зависит от скорости реакции на прерывание. Если у этого прерывания будет не самый высокий приоритет или будут возникать другие прерывания недопускающие вложенность, то будут глюки.


Ок, GetSmart, Вы оказались правы на 100% a14.gif . К сожалению в данном случае мне нужен весь диапазон значений PWM и не удастся ввести постоянную корректировочную составляющую.
Данный проект синуса - это просто тестовый проект который был собран лишь для нахождения глюка.
Насчёт вложенных прерываний - да, придётся сделать вложенность по всей видимости.

Alex03, насчёт RC замнём - фильтруется несущая 40кГц для синуса 50Гц; насчёт ++ тоже в курсе biggrin.gif
У меня в нормальном проекте всего пока 5 прерываний крутится I2C, ADC, 2 периода ПВМ, один из которого системный синхронизующий и второй - достаточно медленный и ещё один таймера сравнения. В целом идей Ваш понятен и принят, насчёт проверок для дебилов - знаете, иногда когда "jmp $" не помогает, очень полезным оказывается писать все проверки и иногда вставлять даже в код NOP biggrin.gif .


--------------------
С уважением,
Go to the top of the page
 
+Quote Post
alexander55
сообщение Jul 8 2008, 10:41
Сообщение #13


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(GetSmart @ Jul 8 2008, 13:36) *
Я оказался прав на 100% smile.gif
Только для обхода этого косяка не обязательно останавливать таймер. Достаточно уменьшить амплитуду синусоиды на несколько процентов чтобы в регистр MR не записывались очень маленькие значения. Например в диапазоне от 25 до 375. Минимально допустимое значение для MR зависит от скорости реакции на прерывание. Если у этого прерывания будет не самый высокий приоритет или будут возникать другие прерывания недопускающие вложенность, то будут глюки.

Вы правы на 100%. Такие глюки я тоже проходил, но с какими-то другими uC.
Автора смутил факт наличия глюка не на самой вершине (из-за фазового сдвига, вносимого R-C цепочкой), а так бы он понял это сразу.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jul 8 2008, 10:56
Сообщение #14


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(cebotor @ Jul 8 2008, 16:26) *
Вопрос - почему нельзя перегружать значение по соответствующему прерыванию (для нулевого канала по прерыванию матча нулевого канала )- будет все хорошо и вперед и назад ? smile.gif
Вот это хорошая идея. Если при срабатывании MATCH-а вызывать прерывание, то можно сразу же перезагружать этот MR регистр. Этот алгоритм подходит когда в сигнале нет резких скачков, как раз для синусоиды. Однако нельзя будет загружать в MR значение большее или равное периоду. Таким образом за один период для трёхканального ШИМа будет три раза срабатывать одно и то же прерывание, в котором анализируя флаг TxIR можно узнать какой MR сработал.
Цитата(avva)
К сожалению в данном случае мне нужен весь диапазон значений PWM и не удастся ввести постоянную корректировочную составляющую.
Остановив таймер Вы её уже ввели smile.gif То есть после обнуления таймера появляются те же ~20 тактов паузы, только они теперь увеличили период с 375 до грубо 395 тактов PCLK. При этом получился плавающий период и нестабильная частота, особенно в присутствии других прерываний.

Сообщение отредактировал GetSmart - Jul 8 2008, 11:04


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
cebotor
сообщение Jul 8 2008, 11:13
Сообщение #15


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 6-04-07
Из: Бронницы
Пользователь №: 26 809



Цитата(GetSmart @ Jul 8 2008, 14:56) *
Однако нельзя будет загружать в MR значение большее или равное периоду.

Cмысл этой фразы для меня остался тайной , по моему и так нельзя загружать в MR значение большее периода smile.gif
Цитата(GetSmart @ Jul 8 2008, 14:56) *
Таким образом за один период для трёхканального ШИМа будет три раза срабатывать одно и то же прерывание, в котором анализируя флаг TxIR можно узнать какой MR сработал.

я честно признаться не помню как в ЛПЦ работает ВИК , так что приходиться ли делить прерывание внутри или снаружи - это зависит от конкретного камня , а вот сама проблема , причину которой вы так удачно предположили - касается практически всех кристаллов в которых нету спец регистров типа прелоад значения smile.gif


--------------------
если еррата пуста - это не хорошо а плохо
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd June 2025 - 00:40
Рейтинг@Mail.ru


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