RGB-контроллер на Atmega8

Собрал на основе статьи "Управление RGB светодиодом c помощью аппаратной ШИМ ATmega8" и "Работа с прерываниями INT0 и INT1" RGB-контроллер.
Пока только три эффекта:
1. Плавная смена цветов с возможностью регулировки скорости смены цвета.
2. Статичный цвет с возможностью выбора цвета.
3. Режим цветного стробоскопа с регулировкой частоты вспышек.

Выкладываю код. Пока в таком виде, т.к. не получается "подсветить" с помощью code language='c' [код программы] /code. :(
Проблема в следующем: при достижении переменной "m" значения 4, программа "повисает" на 243 строке, а было задумано, что начнётся "Плавное изменение цвета" строка 65.
Хотя, те же самые операции с переменной "s" работают, т.е. идёт настройка параметров каждого эффекта по кругу, т.е. 1->16.
Пробовал использовать оператор "goto" с метками, для выбора режимов, но как-то не получается.

Прошу мне помочь! Это моя первая более-менее серьёзная программа. :)

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #include <stdint.h>
  4. #include <util/delay.h>
  5.  
  6. #define R_channel OCR1AL
  7. #define G_channel OCR1BL
  8. #define B_channel OCR2
  9.  
  10. uint8_t volatile s = 1; // начальное значение переменной s
  11. volatile int m = 1; //начальное значение переменной m - "mode"(вид эффекта)
  12. volatile int a = 1; // начальное значение переменной a(величина задержки)
  13. volatile int b = 2500; // начальное значение переменной b(шаг изменения задержки)
  14. volatile int c = 2000; // значение задержки после вывода цвета(сколько времени горит цвет)
  15.  
  16. void pause(uint8_t ms)
  17. {
  18. while(ms--)
  19. _delay_ms(1);
  20. }
  21.  
  22. ISR(INT1_vect)//обработка прерываний INT1 (кнопка "+"/"mode")
  23. {
  24. ++m; //увеличиваем переменную m на 1
  25. if (m == 4)
  26. m = 1;
  27. }
  28.  
  29. ISR(INT0_vect)//обработка прерываний INT0
  30. //(кнопка "-"/настройка праметров режима "mode")
  31. {
  32. ++s; //увеличиваем переменную s на 1
  33. if (s == 16)
  34. s = 1;
  35. }
  36.  
  37. void init_pwm (void)
  38. {
  39. DDRB=0x0e; //Инициализация портов, OC1A,OC1B,OC2 - выходы
  40. TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10);
  41. TCCR1B=(1<<CS10);
  42. TCCR2=(1<<CS20)|(1<<COM21)|(1<<WGM20);
  43.  
  44. OCR1AL=0xff; //Начальный цвет - красный
  45. OCR1BL=0x00;
  46. OCR2=0x00;
  47. }
  48.  
  49. int main(void)
  50. {
  51. unsigned char i;
  52. DDRD = 0x00; //все порты D вход
  53.  
  54. GIMSK=0b11000000; //разрешаем прерывание int0 и int1 - кнопка
  55. MCUCR=0b00001010;// int by falling front - для кнопки 1 и 2(срабатывание при нажатии)
  56. //смотрим datasheet "Table 31. Interrupt Sense Control"
  57.  
  58. sei(); //разрешение прерываний
  59. init_pwm(); //Инициализация ШИМ каналов
  60.  
  61. //Плавное изменение цвета
  62. {
  63. while (m == 1)
  64. {
  65. for(i=0;i<255;i++) //Переход от красного к зеленому
  66. {
  67. R_channel--;
  68. G_channel++;
  69. pause(s);
  70. }
  71. for (i=0;i<255;i++) //Переход от зеленого к синему
  72. {
  73. G_channel--;
  74. B_channel++;
  75. pause(s);
  76. }
  77. for (i=0;i<255;i++) //Переход от синего к красному
  78. {
  79. B_channel--;
  80. R_channel++;
  81. pause(s);
  82. }
  83. }
  84. //Смена цвета
  85. {
  86. while (m == 2)
  87. {
  88. if (s == 1)
  89. {
  90. R_channel = 0xff; //красный
  91. G_channel = 0x00;
  92. B_channel = 0x00;
  93. }
  94. else if (s == 2)
  95. {
  96. R_channel = 0x44;
  97. G_channel = 0x00;
  98. B_channel = 0xff; //фиолетовый
  99. }
  100. else if (s == 3)
  101. {
  102. R_channel = 0x00;
  103. G_channel = 0xff; //зелёный
  104. B_channel = 0x00;
  105. }
  106. else if (s == 4)
  107. {
  108. R_channel = 0x00;
  109. G_channel = 0x00;
  110. B_channel = 0xff; //синий
  111. }
  112. else if (s == 5)
  113. {
  114. R_channel = 0xff; //жёлтый
  115. G_channel = 0xff;
  116. B_channel = 0x00;
  117. }
  118. else if (s == 6)
  119. {
  120. R_channel = 0xff; //розовый
  121. G_channel = 0x00;
  122. B_channel = 0x28;
  123. }
  124. else if (s == 7)
  125. {
  126. R_channel = 0xff; //белый
  127. G_channel = 0xff;
  128. B_channel = 0xff;
  129. }
  130. else if (s == 8)
  131. {
  132. R_channel = 0xff; //оранжевый
  133. G_channel = 0x5c;
  134. B_channel = 0x00;
  135. }
  136. else if (s == 9)
  137. {
  138. R_channel = 0x00; //чёрный
  139. G_channel = 0x00;
  140. B_channel = 0x00;
  141. }
  142. }
  143. }
  144.  
  145. // Режим стробоскопа
  146. {
  147. while (m == 3)
  148. {
  149. R_channel = 0xff;
  150. G_channel = 0x00;
  151. B_channel = 0x00;
  152. _delay_us(c);
  153. R_channel = 0x00; //чёрный
  154. G_channel = 0x00;
  155. B_channel = 0x00;
  156. _delay_us(s*b);
  157. R_channel = 0x00;
  158. G_channel = 0xff;
  159. B_channel = 0x00;
  160. _delay_us(c);
  161. R_channel = 0x00; //чёрный
  162. G_channel = 0x00;
  163. B_channel = 0x00;
  164. _delay_us(s*b);
  165. R_channel = 0x00;
  166. G_channel = 0x00;
  167. B_channel = 0xff;
  168. _delay_us(c);
  169. R_channel = 0x00; //чёрный
  170. G_channel = 0x00;
  171. B_channel = 0x00;
  172. _delay_us(s*b);
  173. R_channel = 0xff;
  174. G_channel = 0xff;
  175. B_channel = 0x00;
  176. _delay_us(c);
  177. R_channel = 0x00; //чёрный
  178. G_channel = 0x00;
  179. B_channel = 0x00;
  180. _delay_us(s*b);
  181. R_channel = 0xff;
  182. G_channel = 0x00;
  183. B_channel = 0x28;
  184. _delay_us(c);
  185. R_channel = 0x00; //чёрный
  186. G_channel = 0x00;
  187. B_channel = 0x00;
  188. _delay_us(s*b);
  189. R_channel = 0x44;
  190. G_channel = 0x00;
  191. B_channel = 0xff;
  192. _delay_us(c);
  193. R_channel = 0x00; //чёрный
  194. G_channel = 0x00;
  195. B_channel = 0x00;
  196. _delay_us(s*b);
  197. R_channel = 0xff;
  198. G_channel = 0x5c;
  199. B_channel = 0x00;
  200. _delay_us(c);
  201. R_channel = 0x00; //чёрный
  202. G_channel = 0x00;
  203. B_channel = 0x00;
  204. _delay_us(s*b);
  205. }
  206. }
  207. }
  208. return 1;
  209. }

Всем спасибо! # if (m!=0)

Всем спасибо! #
if (m!=0) return; // проверка на условие помогла, все переключается как нада.

Убрал режим стробоскопа (тк не очень нужен и места много занимал)

Прошу не пинать ногами, я

Прошу не пинать ногами, я только учусь.
Лепил прогу из кусков,
Поправил нумерацию режимов - помогло.
Еще остался вопрос :
Почему когда выполняется цикл плавного изменения цвета прерывание, int1 срабатывает не сразу, а после того как выполнится последнее условие

  1. {
  2. for (i=0;i<255;i++) //Переход от синего к красному
  3. {
  4. B_channel--;
  5. R_channel++;
  6. pause(s);
  7. }

если скорость маленькая- приходится долго ждать перехода в другой режим.

Делай, как vakula говорит.

  1. {
  2. if (m!=0) return; //
  3. R_channel--;
  4. G_channel++;
  5. pause(s);
  6. }

Потому что у тебя так

Потому что у тебя так построено переключение режимов.
Рассмотрю подробнее. Когда программа выполняется в функции mode1, ты нажимаешь кнопку на INT1. Вызывается прерывание, в котором меняется переменная m. Далее довыполняется функция mode1. После того, как функция mode1 завершилась, производиться проверка режимов, и вызывается следующая функция - mode2.

Это можно устранить, вставив в mode1 проверку вида

if (m!=0) return;

То есть, если было нажатие кнопки - быстро выскочить из mode1, без довыполнения.

А ногами никто не пинает, все когда-то учились.

Спасибо! Добавил в свой код!

Спасибо! Добавил в свой код! :)

Как то странно, я б сделал

Как то странно, я б сделал все режими от проверки одной переменной а не двух, плюс переключение режимов для простоты в одну сторону, жмешь + и меняется режим по цепочке: 1->2->3->1->2->3.

  1. void mode1(void)//режим 1
  2. {
  3. ...
  4. }
  5.  
  6. void mode2(void)//режим 2
  7. {
  8. ...
  9. }
  10.  
  11. void mode3(void)//режим 3
  12. {
  13. ...
  14. }
  15.  
  16. ISR(INT0_vect)//обработка прерываний INT0 //(настройка праметров "mode")
  17. {
  18. ++s; //увеличиваем переменную s на 1
  19. if (s == 16)
  20. s = 1;
  21. }
  22.  
  23. ISR(INT0_vect)//прерывание по
  24. {
  25. m=(m+1)%4;//остаток от деления
  26. //выделяет три значения переменной: 1, 2, 3
  27. }
  28.  
  29. int main (void)
  30. {
  31. ...//инициализация портов и тд. тп.
  32.  
  33. while(1)
  34. {
  35. if (m==1)
  36. {
  37. mode1();//Режим 1
  38. }
  39. else
  40. if (m==2)
  41. {
  42. mode2();//Режим 2
  43. }
  44. else
  45. if(m==3)
  46. {
  47. mode3();//Режим 3
  48. }
  49. }

Подскажите: составил

Подскажите:
составил программу приблизительно по этой модели

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #include <stdint.h>
  4. #include <util/delay.h>
  5. #define R_channel OCR1AL
  6. #define G_channel OCR1BL
  7. #define B_channel OCR2
  8. uint8_t volatile s = 1; // начальное значение переменной s
  9. volatile int m = 1; //начальное значение переменной m - "mode"(вид эффекта)
  10. volatile int a = 1; // начальное значение переменной a(величина задержки)
  11. volatile int b = 2000; // начальное значение переменной b(шаг изменения задержки)
  12. volatile int c = 2000; // значение задержки после вывода цвета(сколько времени горит цвет)
  13.  
  14. void pause(uint8_t ms)
  15. {
  16. while(ms--)
  17. _delay_ms(1);
  18. }
  19. ////////////
  20.  
  21. ISR(INT0_vect)//обработка прерываний INT0
  22. //(кнопка "-"/настройка праметров режима "mode")
  23. {
  24. ++s; //увеличиваем переменную s на 1
  25. if (s == 16)
  26. s = 1;
  27. }
  28.  
  29. ISR(INT1_vect)//обработка прерываний INT1 (кнопка "+"/"mode")
  30. {
  31. m=(m+1)%3;//остаток от деления
  32. //выделяет три значения переменной: 1, 2, 3
  33. }
  34.  
  35. ////////////////////////////////////
  36. void init_pwm (void)
  37. {
  38. DDRB=0x0e; //Инициализация портов, OC1A,OC1B,OC2 - выходы
  39.  
  40. TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10);
  41. TCCR1B=(1<<CS10);
  42. TCCR2=(1<<CS20)|(1<<COM21)|(1<<WGM20);
  43. }
  44.  
  45. int main(void)
  46. {
  47. unsigned char i;
  48. DDRD = 0x00; //все порты D вход
  49. GIMSK=0b11000000; //разрешаем прерывание int0 и int1 - кнопка
  50. MCUCR=0b00001010;// int by falling front - для кнопки 1 и 2(срабатывание при нажатии)
  51. //смотрим datasheet "Table 31. Interrupt Sense Control"
  52. sei(); //разрешение прерываний
  53. init_pwm(); //Инициализация ШИМ каналов
  54.  
  55. void mode1(void)//режим 1
  56. {
  57. OCR1AL=0x00; //Начальный цвет - черный
  58. OCR1BL=0x00;
  59. OCR2=0x00;
  60. OCR1AL=255; // цвет - красный
  61. OCR1BL=0x00;
  62. OCR2=0x00;
  63. for (i=0;i<255;i++) //Переход от красного к зеленому
  64. {
  65. R_channel--;
  66. G_channel++;
  67. pause(s*100);
  68. }
  69.  
  70. for (i=0;i<255;i++) //Переход от зеленого к синему
  71. {
  72. G_channel--;
  73. B_channel++;
  74. pause(s*100);
  75. }
  76. for (i=0;i<255;i++) //Переход от синего к красному
  77. {
  78. B_channel--;
  79. R_channel++;
  80. pause(s*100);
  81. }
  82. }
  83.  
  84. ////////////////////////////////////////////
  85. void mode2(void)//режим 2
  86. {
  87. if (s == 1)
  88. {
  89. R_channel = 0xff; //белый
  90. G_channel = 0xff;
  91. B_channel = 0xff;
  92. }
  93. else if (s == 2)
  94. {
  95. R_channel = 0x00;
  96. G_channel = 0xff;
  97. B_channel = 0xff; //Зеленовато-голубой
  98. }
  99. else if (s == 3)
  100. {
  101. R_channel = 0x7F;
  102. G_channel = 0xFF; //аквамарин
  103. B_channel = 0xD4;
  104. }
  105. else if (s == 4)
  106. {
  107. R_channel = 0x20;
  108. G_channel = 0xB2;
  109. B_channel = 0xAA; //морская волна
  110. }
  111. else if (s == 5)
  112. {
  113. R_channel = 0x00; //зеленый
  114. G_channel = 0xff;
  115. B_channel = 0x00;
  116. }
  117. else if (s == 6)
  118. {
  119. R_channel = 0xff; //желтый
  120. G_channel = 0xff;
  121. B_channel = 0x00;
  122. }
  123. else if (s == 7)
  124. {
  125. R_channel = 0x87; //Orange
  126. G_channel = 0xCE;
  127. B_channel = 0xFA;
  128. }
  129. else if (s == 8)
  130. {
  131. R_channel = 0xff; //оранжевый
  132. G_channel = 0x5c;
  133. B_channel = 0x00;
  134. }
  135. else if (s == 9)
  136. {
  137. R_channel = 0xff; //красный
  138. G_channel = 0x00;
  139. B_channel = 0x00;
  140. }
  141. else if (s == 10)
  142. {
  143. R_channel = 0xFF; //розовый
  144. G_channel = 0xC0;
  145. B_channel = 0xCB;
  146. }
  147. else if (s == 11)
  148. {
  149. R_channel = 0xff; // Magenta (*)
  150. G_channel = 0x00;
  151. B_channel = 0xff;
  152. }
  153. else if (s == 12)
  154. {
  155. R_channel = 0x00; //синий
  156. G_channel = 0x00;
  157. B_channel = 0xff;
  158. }
  159. else if (s == 13)
  160. {
  161. R_channel = 0xee; // Violet
  162. G_channel = 0x82;
  163. B_channel = 0xee;
  164. }
  165. else if (s == 14)
  166. {
  167. R_channel = 0xdd; //Темно-фиолетовый
  168. G_channel = 0xa0;
  169. B_channel = 0xdd;
  170. }
  171. else if (s == 15)
  172. {
  173. R_channel = 0x8a; //Фиолетово-синий 8A2BE2
  174. G_channel = 0x2b;
  175. B_channel = 0xe2;
  176. }
  177. }
  178. ////////////////////////////////////////////
  179. void mode3(void)//режим 3
  180. {
  181. R_channel = 0xff;
  182. G_channel = 0x00;
  183. B_channel = 0x00;
  184. _delay_us(c);
  185. R_channel = 0x8a; //чёрный
  186. G_channel = 0x2b;
  187. B_channel = 0xe2;
  188. _delay_us(s*b);
  189. R_channel = 0x00;
  190. G_channel = 0xff;
  191. B_channel = 0x00;
  192. _delay_us(c);
  193. R_channel = 0x00; //чёрный
  194. G_channel = 0x00;
  195. B_channel = 0x00;
  196. _delay_us(s*b);
  197. R_channel = 0x00;
  198. G_channel = 0x00;
  199. B_channel = 0xff;
  200. _delay_us(c);
  201. R_channel = 0x00; //чёрный
  202. G_channel = 0x00;
  203. B_channel = 0x00;
  204. _delay_us(s*b);
  205. R_channel = 0xff;
  206. G_channel = 0xff;
  207. B_channel = 0x00;
  208. _delay_us(c);
  209. R_channel = 0x00; //чёрный
  210. G_channel = 0x00;
  211. B_channel = 0x00;
  212. _delay_us(s*b);
  213. R_channel = 0xff;
  214. G_channel = 0x00;
  215. B_channel = 0x28;
  216. _delay_us(c);
  217. R_channel = 0x00; //чёрный
  218. G_channel = 0x00;
  219. B_channel = 0x00;
  220. _delay_us(s*b);
  221. R_channel = 0x44;
  222. G_channel = 0x00;
  223. B_channel = 0xff;
  224. _delay_us(c);
  225. R_channel = 0x00; //чёрный
  226. G_channel = 0x00;
  227. B_channel = 0x00;
  228. _delay_us(s*b);
  229. R_channel = 0xff;
  230. G_channel = 0x5c;
  231. B_channel = 0x00;
  232. _delay_us(c);
  233. R_channel = 0x00; //чёрный
  234. G_channel = 0x00;
  235. B_channel = 0x00;
  236. _delay_us(s*b);
  237. }
  238. ////////////////////////////////////////////////////////
  239. init_pwm(); //Инициализация ШИМ каналов
  240. //Плавное изменение цвета
  241. while(1)
  242. {
  243. if (m==1)
  244. {
  245. mode1();//Режим 1
  246. }
  247. else
  248. if (m==2)
  249. {
  250. mode2();//Режим 2
  251. }
  252. else
  253. if(m==3)
  254. {
  255. mode3();//Режим 3
  256. }
  257. }
  258. return 1;
  259. }

Вопрос: почему по прерыванию INT 0 переключается скорость/ цвет сразу же,
а по INT 1 режим переключается не сразу. Прерывание ведь важнее обычных операций?
Например если работает 1-й режим- перелив цвета скорость можно изменить сразу же,
если нажать на кнопку режима то смена режима не осуществится пока не завершится
1-й режим - цвет не дойдет до красного.

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

По поводу каши я тоже

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

Вот так вот не гласно принято оформлять код. Оно читается тогда хорошо, все сразу видно.
Легко проанализировать и разобраться.

У тебя проверка режимов

У тебя проверка режимов начинается с 1-цы
Вот.

  1. while(1)
  2. {
  3. if (m==1)
  4. {
  5. mode1();//Режим 1
  6. }
  7. else if (m==2)
  8. {
  9. mode2();//Режим 2
  10. }
  11. else if(m==3) {
  12. mode3();//Режим 3
  13. }

А "переключалка" режимов работает от 0 до 2.
  1. ISR(INT1_vect)//обработка прерываний INT1 (кнопка "+"/"mode")
  2. {
  3. m=(m+1)%3;//остаток от деления
  4. //выделяет три значения переменной: 1, 2, 3
  5. }

То есть, переменная m может принимать значения от 0 до 2 включительно.
А в коде выше, ты сравнивает m с 3.

И еще, оформь покрасивей функции, то я как-то сразу не понял, где main(), а где остальные функции. Каша.

В данном случаи очень помогло

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

Вот видео работы. Качество

Вот видео работы. Качество оставляет желать лучшего... но.
Сомневаюсь что видео сильно поможет...
Третий режим- стробоскоп, код написал San в том исходнике, что он прислал, этот фрагмент кода мигал,

если не секрет, что это за

если не секрет, что это за лента такая? где покупается, и сколько примерно стоит?
ну и марку ее конечно, тоже, если можно.

лента с смд rgb светодиодами.

лента с смд rgb светодиодами. Покупается на ближайшем радиорынке, в случае Киева это Кар-Дачи, цена по разному, в зависимости от плотности забивки светодиодами

Ура! Тема интересна не мне одному. :)

Что подсвечивать собрался? Мебель, машину? :)
А чтобы не останавливаться на достигнутом можно ещё сделать изменение цветов и режимов под музыку.
И ещё ИК пульт приделать неплохо было бы.

А вот исправление, чтобы в режиме "Плавное изменение цвета" можно было сразу менять режим и не ждать до "красного".

  1. void mode1(void) //режим 1 //Плавное изменение цвета
  2. {
  3. unsigned char i;
  4. for (i=0;i<255;i++) //Переход от красного к зеленому
  5. {
  6. if (m!=0) return;
  7. R_channel--;
  8. G_channel++;
  9. pause(s);
  10. }
  11. for (i=0;i<255;i++) //Переход от зеленого к синему
  12. {
  13. if (m!=0) return;
  14. G_channel--;
  15. B_channel++;
  16. pause(s);
  17. }
  18. for (i=0;i<255;i++) //Переход от синего к красному
  19. {
  20. if (m!=0) return;
  21. B_channel--;
  22. R_channel++;
  23. pause(s);
  24. }
  25. }

Удалось "подсветить" код! :)

Спасибо! Помогло!

Заработало! Только в выражении m=(m+1)%4, четвёрку поменял на 3, и m==0, m==1, m==2.
:)

Вот такой вопросик теперь: как картинки и видео youtube вставлять в форум? Хотелось бы оформить в нормальном виде всё: схему, фотки и видео работы готового устройства выложить хочу. :)

Ага, завтыкал с количеством

Поздравляю :) Ага, завтыкал с количеством режимов.
Статью можно оформить следующим образом. Заходим в Create content->Story.
Картинки вставить так:
"img src="http://avrlab.com/upload_files/rec_front.jpg" alt="фото GPS приемника" width="600" height="400" /"
Вместо первой и последней " надо поставить < и > соответственно.
Картинки и другие файлы можно загрузить на сайт с помощью File attachments. Таже стоит input format поставить как ас.
Видео же с ютуба вставляются таким образом: на запущенном видео клацаем правой клавишей, появится меню, в нем выбираем "Copy embed html" потом этот код вставляем в статью.

Окей. Сделаю фото-

Окей. Сделаю фото- видеоматериалов и будет статья. :)
По программе: пугают такие строчки - Program: 7670 bytes (93.6% Full). А если убрать из программы "режим стробоскопа", то гораздо меньше занимает места.Чего-то я набакланил...

Так же обрати внимание в

Так же обрати внимание в свойстве проэкта в AVR Studio есть пункт "Оптимизация", попробуй поиграться со значением степени оптимизации. Бывали случаи уменьшения кода до 50% :-)
Правда бывали и негативные случаи, начинались сбои в работе библиотеки delay.h

Тип double в функции

Тип double в функции _delay_us(double __us) жрет очень много флеш-памяти, попробуй как-то иначе организовать задержку. Т.е. использовать функцию

  1. void s_delay(void)
  2. {
  3. _delay_us(s*b);
  4. }
  5. размер кода должен уменьшится.

Код для умножения и преобразования в double будет всего 1 раз прописан в программе, а не N раз, как у тебя.

Выбери Create Content а потом

Выбери Create Content а потом Story.
Будет страница со статьей как все остальные на сайте.
Пиши побольше описания, читать будут и начинающие тоже, больше подробностей - больше внимания пользователей, больше вопросов :-)

А попробуй ++s; //увеличиваем

А попробуй

  1. ++s; //увеличиваем переменную s на 1
  2.  
  3. ++m; //увеличиваем переменную m на 1

в прерываниях по INT0,INT1 заменить на следующее:
  1. s=s+1;
  2. m=m+1;

Мне встречались глюки с оператором i++, если i - int-товская переменная.

Стоит не забывать о дребезге контактов, может втулить в прерывание код вида:

  1. ISR(INT0_vect)
  2. {
  3. pause(10);
  4. while ((PIND&_BV(2))==0x00) //пока клавиша зажата - ждем ее отжатия
  5. ;
  6.  
  7. s=(s+1);
  8. if (s==16) s=1;
  9. }

Вместо конструкции

  1. ++m; //увеличиваем переменную m на 1
  2. if (m == 4)
  3. m = 1;

можно использовать m=(m+1)%4, % - остаток от деления. Переменная m будет принимать значения от 0 до 3. Но это на вкус и цвет :)

Также я бы поменял местами строки,

  1. sei(); //разрешение прерываний
  2.  
  3. init_pwm(); //Инициализация ШИМ каналов

но это тоже больше для красоты. Т.е. сперва полностью инициализируем все, а потом уже врубаем прерывания.

Дребезг контактов 100% будет

Дребезг контактов 100% будет надо ставить

  1. ISR(INT0_vect)
  2. {
  3. pause(10);
  4. while ((PIND&_BV(2))==0x00);
  5. //пока клавиша зажата - ждем ее отжатия
  6. s=(s+1);
  7. if (s==16) s=1;
  8. }

И по поводу поменть местами согласен потому что это немого не корректно будет разрешить прерывания раньше чем инициализация ШИМ.

Дребезг

Дребезг убрал аппаратными средствами пока. 100 нФ на землю.