Главная » Микроконтроллеры
Призовой фонд
на май 2017 г.
1. Тестер компонентов MG328
Паяльник
2. Осциллограф DSO138
Паяльник
3. Регулируемый паяльник 60 Вт
Паяльник
4. 100 руб.
От пользователей

Программный ШИМ на STM8L

В данной статье я хочу рассказать о программном создании ШИМ-регулятора на STM8L-Discovery. Проект полностью переносим на другие микроконтроллеры типа STM8. Процесс переноса описан неоднократно, в т.ч. и мной в статье Термометр на STM8L-Discovery

Итак для начала разберёмся, что такое ШИМ. Широтно-импульсная модуляция - это процесс управления средней мощностью в нагрузке за счет изменения коэффициента заполнения сигнала прямоугольной формы. По определению средняя мощность Pсредняя= U2среднее/Rнагрузки. Не будем вдаваться в математические подробности, просто отмечу, что Uсреднее = Umax*t1/t2. Отношение t1/t2 ещё называют коэффициентом заполнения.

Пояснения на рисунке 1.

Таким образом, наша задача генерировать прямоугольные импульсы с различным коэффициентом заполнения. Она, в свою очередь, сводится к тому, чтобы управлять ножкой микроконтроллера, переводя её то в положение "1", то в положение "0". Кажется, что мы получили простое решение задачи: бесконечный цикл, где мы поднимаем выход, ждем, опускаем выход, ждем. Есть одно но: бесконечный цикл подвесит ядро, поэтому никаких других функций после запуска ШИМ мы выполнить не сможем (можно, конечно, извернуться и что-нибудь придумать с прерываниями, но это уже извращения). Поэтому я предлагаю другой способ - с прерываниями от таймера. Смысл такой: таймер дает прерывания, скажем, раз в 10 нс - это и будет нашим минимальным значением длительности импульса, или МЗДИ. Далее, возьмем период в 256 МЗДИ. Теперь нам нужна переменная, в которой будет храниться значение длительности импульса - от 0 до 255; соответственно коэффициент заполнения будет от 0 до 1, а средняя мощность нагрузки от 0% до 100%. Теперь посмотри на мою реализацию данного алгоритма

int _q, count;

//описание прерывания
#pragma vector = 27
__interrupt void tim4_ovf( void )
{
  if ( count < _q ) // если от начала периода прошло меньше времени импульса
    PC_ODR_bit.ODR5 = 1; //то на выходе "1"
  else //иначе
    PC_ODR_bit.ODR5 = 0; //"0"
  count++; //увеличим счетчик времени
  if ( count >= 256 ) //если период закончился
    count = 0; //сбросим счетчик
  TIM4_SR1_bit.UIF = 0; //выйдем из прерывания
}

void line_PWM( int q )
{
  asm( "RIM" );  //разрешаю прерывания
  CLK_PCKENR1_bit.PCKEN12 = 1; // подаю тактирование
  TIM4_PSCR = 0x00; //ставлю предделители
  TIM4_ARR = 0x0D;
  TIM4_IER_bit.UIE = 1; //ставлю биты конфигурации 
  TIM4_CR1_bit.URS = 1;
  TIM4_EGR_bit.UG = 1;
  TIM4_CR1_bit.CEN = 1;  //запускаю таймер
  count = 0; //сброс счетчика прерываний
  PC_DDR_bit.DDR5 = 1; //нога на выход
  PC_CR1_bit.C15 = 1;
  _q = q; //сохранили аргумент команды - длительность импульса
}

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

const int table[256] = {0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
1,
1,
1,
2,
2,
2,
2,
2,
3,
3,
3,
3,
4,
4,
4,
4,
5,
5,
5,
5,
6,
6,
6,
7,
7,
7,
8,
8,
9,
9,
9,
10,
10,
11,
11,
11,
12,
12,
13,
13,
14,
14,
15,
15,
16,
16,
17,
17,
18,
18,
19,
19,
20,
20,
21,
22,
22,
23,
23,
24,
25,
25,
26,
27,
27,
28,
29,
29,
30,
31,
31,
32,
33,
33,
34,
35,
36,
36,
37,
38,
39,
40,
40,
41,
42,
43,
44,
44,
45,
46,
47,
48,
49,
50,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
79,
80,
81,
82,
83,
84,
85,
87,
88,
89,
90,
91,
93,
94,
95,
96,
97,
99,
100,
101,
102,
104,
105,
106,
108,
109,
110,
112,
113,
114,
116,
117,
118,
120,
121,
122,
124,
125,
127,
128,
129,
131,
132,
134,
135,
137,
138,
140,
141,
143,
144,
146,
147,
149,
150,
152,
153,
155,
156,
158,
160,
161,
163,
164,
166,
168,
169,
171,
172,
174,
176,
177,
179,
181,
182,
184,
186,
188,
189,
191,
193,
195,
196,
198,
200,
202,
203,
205,
207,
209,
211,
212,
214,
216,
218,
220,
222,
224,
225,
227,
229,
231,
233,
235,
237,
239,
241,
243,
245,
247,
249,
251,
253,
255
};

void LED_PWM( int q )
{
  
  line_PWM( table[q] );
}

В главном файле напишем простую обвязочку для тестирования функций ШИМ

void delay( void )
{
  for ( int i =0; i < 20; i++ );
}

int main()
{
  CLK_CKDIVR = 0;
  while ( true )
  {
    for ( long int i = 0; i <= 255; i++ )
    {
      line_PWM(i);
      delay();
    }
    for ( long int i = 255; i >= 0; i-- )
    {
      LED_PWM(i);
      delay();
    }
  }
  return 0;
}

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

Прикрепленные файлы:

Теги:

Опубликована: 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (3) | Я собрал (0) | Подписаться

0
Константин #
Подскажите пожалуйста - реально ли собрать шим с регулировкой по скважности для инверторного сварочного аппарата, полного моста? Аналоговые заколупался паять - все не стабильно, ступенька срывается, ключи горят... Нужен именно программный ШИМ!
Ответить
0

[Автор]
Стальной #
Всё реально. Только зачем?
Ответить
0

[Автор]
Стальной #
На всякий случай пример аппаратного шим, таймер 2, вывод PB0

CLK_CKDIVR = 0;
CLK_PCKENR1_bit.PCKEN10 = 1;
TIM2_PSCR_bit.PSC = 0x00;
TIM2_ARRH = 0xFF;
TIM2_ARRL = 0xFF;
TIM2_CR1_bit.URS = 1;

TIM2_CR1_bit.CMS = 1;
TIM2_CR1_bit.ARPE = 1;
TIM2_BKR_bit.MOE = 1;
TIM2_CCER1_bit.CC1E = 1;
TIM2_CCMR1_bit.OC1PE = 1;
TIM2_BKR_bit.OSSI = 0;
TIM2_CCER1_bit.CC1P = 0;
TIM2_CCR1H = 0x7F;
TIM2_CCR1L = 0xFF;
TIM2_CCMR1_bit.OC1M = 6;
TIM2_EGR_bit.UG = 1;
TIM2_IER_bit.UIE = 1;
TIM2_CR1_bit.CEN = 1;
TIM2_CCR1 - значение счетных регистров, при котором закончится импульс
Сам не особо проник в детали пока что, но вдруг кому пригодится.
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется электрическая мощность?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Программатор Pickit3
Программатор Pickit3
200 Вт усилитель класса D на IRS2092 Макетная плата для пайки (10 шт)
вверх