Я так понимаю, что надо в теле обработчика прерывания таймера3 запускать таймер2, но как это корректно сделать - не понимаю... Можно ли это реализовать просто включением таймера 2 или разрешением прерываний от него?Ser60 писал(а):Начите с настройки первого таймера на 50 гц и добейтесь зыдачи этой частоты на ногу МК (см. книгу Гладштейна). Когда с этим разберетесь, напишите код как-бы Вы управляли внешним ключевым транзистором и выведите соответствующие сигналы на другую ногу МК. После этого пришлите код для дальнейшего обсуждения.
подключение к USB
Вы выше писали:
- Реклама
- Сообщения: 3784
- Зарегистрирован: Ср дек 24, 2008 09:58:58
Для запуска тамера 2 надо поставить 1 в бит 2 (TR2) регистра TMR2CN. Аналогично для таймера 3 - бит 2 (ТR3) в регистре TMR3CN.
Для визуального контроля импульсов формируемых таймером, я-бы подключился осциллографом на ноги МК, контролируемые таймерами 2 и 3. И все-же рекомендую начать с одного цвета.
Для визуального контроля импульсов формируемых таймером, я-бы подключился осциллографом на ноги МК, контролируемые таймерами 2 и 3. И все-же рекомендую начать с одного цвета.
То есть вот так будет корректно? (заменены команды P1 |=0x01; и P1 &=0xFE; на ET2=1; и ET2=0; соответственно)
Спойлер
Код: Выделить всё
if(alsn1==1)
{if (alsn2==35)
{alsn1=alsn1+1;
ET2=0;
alsn2=0;}
else {
ET2=1;
alsn2=alsn2+1;
}
}
else{
if (alsn1==2||alsn2==4)
{
if (alsn2==12)
{
ET2=1;
alsn1=alsn1+1;
alsn2=0;
}
else
{
ET2=0;
alsn2=alsn2+1;}
}
if (alsn1==3||alsn1==5)
{if (alsn2==24)
{ET2=0;
alsn1=alsn1+1;
alsn2=0;}
else
{ET2=1;
alsn2=alsn2+1;}}
else
{if (alsn2==79)
{ET2=1;
alsn1=1;
alsn2=0;}
else
{ET2=0;
alsn2=alsn2+1;}}}}- Сообщения: 3784
- Зарегистрирован: Ср дек 24, 2008 09:58:58
Команда
ET2=0;
написана верно, а все остальное уж очень неэффективно. Я все еще не понял идеи Вашего кода.
Я-бы сделал так на примере зеленого цвета: в течении периода имеются 6 подинтервалов. Завести массив из 6 чисел, соответствующих длительностям этих подинтервалов (длительности 0.35, 0.12, и т.д). В прерывании таймера (по истечении подинтервала выдержки) загружать в него следующее значение для выдержки по циклу (после 6-го идет опять первое). Будет около 5 строчек на цвет.
ET2=0;
написана верно, а все остальное уж очень неэффективно. Я все еще не понял идеи Вашего кода.
Я-бы сделал так на примере зеленого цвета: в течении периода имеются 6 подинтервалов. Завести массив из 6 чисел, соответствующих длительностям этих подинтервалов (длительности 0.35, 0.12, и т.д). В прерывании таймера (по истечении подинтервала выдержки) загружать в него следующее значение для выдержки по циклу (после 6-го идет опять первое). Будет около 5 строчек на цвет.
Спасибо, идея с массивом мне в голову не приходила. Получается надо в начале сравнить со значением числа в массиве и в случае совпадения изменить состояние таймера, генерирующего 50 Гц и перейти к следующему числу в массиве? У меня в начале проверяется номер подинтервала, затем длительность и определяется нужно ли менять состояние таймера, генерирующего 50 Гц
- Реклама
- Сообщения: 3784
- Зарегистрирован: Ср дек 24, 2008 09:58:58
Не совсем. Сначала заводите массив длительностей. На примере для зеленого цвета пусть это будет массив из 6-ти элементов по числу генерируемых подинтервалов с длительностями 0.35, 0.12, 0.22, 0.12, 0.22, 0.57 сек.
int green[] = {*, *, *, *, *, *};
Вместо звездочек туда нужно подставить реальные числа, соответствующие длительностям. Для их нахождения примем, что частота импульсов на входе таймера 1.5 мгц (период 2/3 мксек) и используется предделитель 1:48. Для получения первой выдержки 0.35 сек = 350000 мксек таймер должен будет досчитать до числа х определяемого из равенства
(2/3)*48*х = 350000
откуда получаем x = 10937. Поскольку таймер обнуляется при переходе от 65535 в 0, для получения выдержки 0.35 сек в его счетчик следует загрузить число 65536 - х = 54599. Это и будет первый элемент массива green. Для второго элемента массива и выдержки 0.12 сек аналогично получаем x = 3750, т.е. второй эемент будет 65536 - 3750 = 61786 и т.д. Поскольку Timer3 не имеет предделителя 1:48, вместо него следует использовать Timer0 или Timer1.
После того как массив сформирован, в основной программе перед запуском генерации зеленого цвета заводите переменную
int index = 0;
в которой хранится индекс элемента массива green отрабатываемой в таймере задержки. После этого запускаете таймер и искусственно инициируете его переполнение путем записи 1 в его флаг прерывания. Это вызовет обработчик прерывания для отработки первой задержки.
Теперь в обработчике прерывания делаете следующее:
1. Загружаете в счетчик таймера очередной элемент green[index]:
TMR0 = green[index];
2. Для четных значений индекса следует запускать генерацию 50 гц, для нечетных гасить. В последнем случае следует насильственно заисать 0 в пин порта, чтобы при остановке таймера 50гц на выходе пина был 0.
if (index & 1) // нечетные значения index
{
Stop timer 50 Hz;
P0.* = 0; // вместо * должен стоять конкретный номер пина.
}
else // четные значения index
Start Timer 50 Hz;
3. Увеличиваете индекс массива по модулю 6:
if (++index == 6)
index = 0;
Флаги прерывания от таймеров 0 и 1 автоматически сбрасываются при обработке прерывания.
int green[] = {*, *, *, *, *, *};
Вместо звездочек туда нужно подставить реальные числа, соответствующие длительностям. Для их нахождения примем, что частота импульсов на входе таймера 1.5 мгц (период 2/3 мксек) и используется предделитель 1:48. Для получения первой выдержки 0.35 сек = 350000 мксек таймер должен будет досчитать до числа х определяемого из равенства
(2/3)*48*х = 350000
откуда получаем x = 10937. Поскольку таймер обнуляется при переходе от 65535 в 0, для получения выдержки 0.35 сек в его счетчик следует загрузить число 65536 - х = 54599. Это и будет первый элемент массива green. Для второго элемента массива и выдержки 0.12 сек аналогично получаем x = 3750, т.е. второй эемент будет 65536 - 3750 = 61786 и т.д. Поскольку Timer3 не имеет предделителя 1:48, вместо него следует использовать Timer0 или Timer1.
После того как массив сформирован, в основной программе перед запуском генерации зеленого цвета заводите переменную
int index = 0;
в которой хранится индекс элемента массива green отрабатываемой в таймере задержки. После этого запускаете таймер и искусственно инициируете его переполнение путем записи 1 в его флаг прерывания. Это вызовет обработчик прерывания для отработки первой задержки.
Теперь в обработчике прерывания делаете следующее:
1. Загружаете в счетчик таймера очередной элемент green[index]:
TMR0 = green[index];
2. Для четных значений индекса следует запускать генерацию 50 гц, для нечетных гасить. В последнем случае следует насильственно заисать 0 в пин порта, чтобы при остановке таймера 50гц на выходе пина был 0.
if (index & 1) // нечетные значения index
{
Stop timer 50 Hz;
P0.* = 0; // вместо * должен стоять конкретный номер пина.
}
else // четные значения index
Start Timer 50 Hz;
3. Увеличиваете индекс массива по модулю 6:
if (++index == 6)
index = 0;
Флаги прерывания от таймеров 0 и 1 автоматически сбрасываются при обработке прерывания.
Большое спасибо!
Сейчас сделал то, что Вы написали. компилятор ругается на "TMR0 = green[index];" пишет *** ERROR C202 IN LINE 313 OF USB_MAIN.C: 'TMR0': undefined identifier . Я так понимаю, что число из массива надо разбить на 2 части и по отдельности записать в TMR0H и TMR0L? Если да, то как это можно сделать?
- Сообщения: 3784
- Зарегистрирован: Ср дек 24, 2008 09:58:58
Да, Вы правы. Загрузить побайтно переменную period типа int в счетчик таймера можно, например, так:
TH0 = *((char*)&period+1);
TL0 = *(char*).
TH0 = *((char*)&period+1);
TL0 = *(char*).
Прошу прощения, не понял: что обозначает * после оператора присвоения и после char, и что обозначает period?
- Сообщения: 3784
- Зарегистрирован: Ср дек 24, 2008 09:58:58
Вместо period в Вашем случае следует подставить элемент массива green[index].
A звездочки нужны для того, чтобы заставить компилятор С обратиться к байтам переменной типа int, занимающей 2 байта. Конструкцией &period получает адрес переменной period, затем (char*)&period преобразует адрес (pointer) на переменную типа int в адрес на 1-байтовую переменную типа char (по-английски это называется casting). После того как получен адрес на байт, еще одна здездочка в *(char*)&period нужна для доставания переменной по этому адресу (по англ. это dereferencing the pointer). Также и в загрузке TH0, но там следует перед dereferencing добавить к адресу 1 для доступа к старшему байту числа. Все эти ухищрения нужны для генерации кода типа такого:
mov A, period
mov TH0, A
mov A, period+1
mov TL0, A
A звездочки нужны для того, чтобы заставить компилятор С обратиться к байтам переменной типа int, занимающей 2 байта. Конструкцией &period получает адрес переменной period, затем (char*)&period преобразует адрес (pointer) на переменную типа int в адрес на 1-байтовую переменную типа char (по-английски это называется casting). После того как получен адрес на байт, еще одна здездочка в *(char*)&period нужна для доставания переменной по этому адресу (по англ. это dereferencing the pointer). Также и в загрузке TH0, но там следует перед dereferencing добавить к адресу 1 для доступа к старшему байту числа. Все эти ухищрения нужны для генерации кода типа такого:
mov A, period
mov TH0, A
mov A, period+1
mov TL0, A
Все, разобрался, спасибо! Еще появился вопрос: в книжке Николайчука упоминается, что интерфейс C2 является одной из версий JTAG, и что МК семейства С8051 можно прошивать через JTAG. Это относится ко всему семейству, или только к отдельным МК? (спрашиваю, так как фирменный программатор еще не купил)
- Сообщения: 3784
- Зарегистрирован: Ср дек 24, 2008 09:58:58
JTAG поддерживают только очень немногие модели семейства C8051. В частности, F340 программируется только через C2.
Понятно, жаль... А с обработчиком прерывания я правильно понимаю, что для того, что бы завести другие сигналы, надо сделать такой же алгоритм обработчика как и с зеленым, только исправив название массива и условие обнуления переменной index?
- Сообщения: 3784
- Зарегистрирован: Ср дек 24, 2008 09:58:58
Да, Вы все правильно поняли. Еще следует завести переменную, например, color, в которой будет код генерируемого цвета и в обработчике прерываний устроить case соответствующий ее значением с кодами для генерации соответствующих цветов.
Кстати, я давно хотел написать, что по-видимому эта дискуссия никого более не интересует. Что если мы передем на общение через личные сообщения, дабы не засорять форум? Если согласны - в следующий раз пишите сразу туда.
Кстати, я давно хотел написать, что по-видимому эта дискуссия никого более не интересует. Что если мы передем на общение через личные сообщения, дабы не засорять форум? Если согласны - в следующий раз пишите сразу туда.


