Консультация № 186698
12.10.2012, 13:06
212.60 руб.
0 6 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:Помогите пожалуйста дописать программу на С++.
Итак,из порта USB, через аппаратный мост FTDI 245 (преобразует USB в параллельный порт) поступает определенная цифра. Микроконтроллер AT Mega8 считывает её и устанавливает на выходах либо 1 либо генерирует прерывистый сигнал частотой 1КГц через 0,5 сек. Написал начало, дальше никак, не могу расписать генерацию:
#include<stdio.h>
#include<iostream.h>
#include<avr/io.h>
#include<avr/interrupt.h>
#define F_CPU1000000 //устанавливаем частоту МК 1МГц
#define INI 255
unsigned char a,d,i,c; //оператор описания переменных а,d,i,c
int s=0b11001100; // сигнал "s" -событие=204=0ХСС=0b11001100
int v=0b11100111; //сигнал "v"- авария=231=0ХЕ7=0b1110011
int main(void)
{ //первая открывающая скобка цикла
DDRB=0b11111111; //инициализация регистра DDR порта В
PORTB=0b00000000; //порт В-все линии выходы с лог. 0
DDRD=0b00000000; //инициализация регистра DDR порта D
PORTD=0b00000000; //порт D-все линии входы
DDRC=0b1100000; //инициализация регистра DDR порта С
PORTC=0b0011111; //порт С-все линии порта входы, кроме РС5 и РС6
PORTD=0b11111111; // порт D -все линии входы с подтягивающими резисторами.
sei(); //разрешаем прерывания глобально
while(1) //бесконечный цикл опроса порта D
{ //открывающая скобка "тела" цикла
a=PIND; //читаем порт D
if(a==v){PORTC=0b10000000; continue;} //если в порту D авария то на РС6 уст. лог 1
if (a==s) {PORTC=0b0100000; continue;} //
PORTC=0b00000000; // если ни одно условие не выполняется то в порт С записываем все лог.0
}
}

Обсуждение

давно
Посетитель
7438
7205
12.10.2012, 15:01
общий
12.10.2012, 16:22
Во-первых, слегка подправил Ваш код. Сравните...[code h=200]#include<stdio.h>
#include<iostream.h>
#include<avr/io.h>
#include<avr/interrupt.h>

#define F_CPU 1048576 //устанавливаем частоту МК 1МГц
#define INI 255

unsigned char a,d,i,c; //оператор описания переменных а,d,i,c

int s=0b11001100; // сигнал "s" -событие=204=0ХСС=0b11001100
int v=0b11100111; //сигнал "v"- авария=231=0ХЕ7=0b1110011

int main(void)
{ //первая открывающая скобка цикла
DDRB= 0b11111111; //инициализация регистра DDR порта В
PORTB=0b00000000; //порт В-все линии выходы с лог. 0
DDRD= 0b00000000; //инициализация регистра DDR порта D
PORTD=0b11111111; //порт D -все линии входы с подтягивающими резисторами.
DDRC= 0b01100000; //инициализация регистра DDR порта С
PORTC=0b10011111; //порт С-все линии порта входы, кроме РС5 и РС6

sei(); //разрешаем прерывания глобально

while(1) //бесконечный цикл опроса порта D
{ //открывающая скобка "тела" цикла
a=PIND; //читаем порт D
if(a==v)
PORTC=0b01000000; //если в порту D авария то на РС6 уст. лог 1
else if (a==s)
PORTC=0b00100000;
else
PORTC=0b00000000; // если ни одно условие не выполняется то в порт С записываем все лог.0
}
}[/code]
Во-вторых, уточните, что понимается под "Mega8 считывает цифру и устанавливает на выходах либо 1 либо генерирует прерывистый сигнал частотой 1КГц через 0,5 сек"?
1) какие значения принимаются? В программе используются только 0xCC и 0xE7.
2) В программе генерируются 1 или на PC6 , или на PC5 (может, неправильно понял?)
Где должен генерироваться "прерывистый сигнал" (так понимаю, меандр (то 1, то 0)?)?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
13.10.2012, 06:13
общий
13.10.2012, 15:11
Доброго времени суток, Игорь Витальевич!
1. Если на входе Mega8 (порт В) появляется 0ХСС (событие), то на РС6 устанавливается лог. 1
2. Если на входе Mega8 (порт В) появляется 0хЕ7 (авария), то на РС5 действительно идет меандр, но заполненный прямоугольными импульсами, я указал на рисунке.

Прикрепленные файлы:
68f2abf804df5abb1e0b1ee3ba932121.BMP
давно
Посетитель
7438
7205
13.10.2012, 15:15
общий
BMP-шки не идут.
Ок, я понял. Сделаем...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
13.10.2012, 17:30
общий
В целом накидал, но ответ дам в понедельник.
Дома не имею возможности проверить правильность написания,
т.к. лично я для AVR-ок предпочитаю ассемблер
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
14.10.2012, 07:03
общий
Спасибо, исправил значение частоты процессора. Моделирую в VMLab, пишу в WinAVR-20100110.
давно
Посетитель
7438
7205
15.10.2012, 13:35
общий
это ответ
Здравствуйте, Давыдов Сергей Владимирович!
Для получения результата не обойтись без прерывания таймера.
Воспользуемся таймером 0. Для которого задаем делитель = 8, т.к.
данный таймер 8-битный и без делителя необходимое значение
просто не поместится в регистр. Можно было использовать 16-битный таймер 1,
но, полагаю, это совершенно не принципиально.
Таймер загружаем таким значением, чтобы он срабатывал каждый полупериод
нашего меандра, т.к. нам необходимо переключать значения порта.
Кроме того, считаем данные прерывания в переменной типа int (2 байта)
Для первой тысячи обнуляем порт, для второй для каждого прерывания меняем значение порта

[code h=200]#include<avr/io.h>
#include<avr/interrupt.h>
#include <avr/iom8.h>
#define F_CPU 1048576L //устанавливаем частоту МК 1МГц
#define TICK_COUNT 65 //(500*F_CPU)/(1000000*8)
//число тиков таймера равно длине полупериода = 500мкс,
//деленной на время тика процессора в мкс (1000000/F_CPU)
//и деленной на делитель таймера (8)
#define TIMER_INIT (256-TICK_COUNT) //таймер растет до переполнения 255->0
#define TIMER_COUNT 2000 //число полупериодов в 1 сек (1000Гц*2)

unsigned char a; //оператор описания переменных а
unsigned char s=0b11001100; //сигнал "s" -событие=204=0ХСС=0b11001100
unsigned char v=0b11100111; //сигнал "v"- авария=231=0ХЕ7=0b1110011
int count; //счетчик полупериодов

int main(void)
{
DDRB= 0b11111111; //инициализация регистра DDR порта В
PORTB=0b00000000; //порт В-все линии выходы с лог. 0

DDRD= 0b00000000; //инициализация регистра DDR порта D
PORTD=0b11111111; //порт D -все линии входы с подтягивающими резисторами.
DDRC= 0b01100000; //инициализация регистра DDR порта С
PORTC=0b10011111; //порт С-все линии порта входы, кроме РС5 и РС6

TCCR0 = 1<<CS01; //делитель clk/8 (1048576/8 = 131072)
//1 тик таймера = 1/131072 = 7,62939453125 мкс
//500 мкс (1 полупериод) = 65,536 * 7,62939453125
TCNT0 = TIMER_INIT; //инициируем счетчик таймера
TIMSK = 1<<TOIE0; //разрешаем прерывания от 0 таймера
count = TIMER_COUNT; //иницируем счетчик полупериодов

sei(); //разрешаем прерывания глобально
while(1){} //пустой основной цикл, вся работа в прерывании
}

SIGNAL (SIG_OVERFLOW0) //прерывание 0 таймера
{
TCNT0 = TIMER_INIT; //инициируем заново счетчик
a = PIND; //читаем код
if (a==v) //авария?
{
PORTC |= _BV(6); //если в порту D авария то на РС6 уст. лог 1
PORTC &= _BV(5); //если в порту D авария то на РС5 уст. лог 0
}
else if (a==s) //событие?
{
PORTC &= ~_BV(6); //на РС6 уст. лог 0

if (--count == 0) //уменьшаем счетчик до 0
count = TIMER_COUNT; //если нуль, то инициируем заново
if (count < (TIMER_COUNT/2))//если первые 0.5 с
PORTC &= ~_BV(5); //то на РС5 уст. лог 0
else if (count & 1) //во второй половине для нечетных
PORTC |= _BV(5); //взводим 1
else //для четных
PORTC &= ~_BV(5); //взводим 0
//т.о., получаем меандр с частотой 1КГц
}
else // если ни одно условие не выполняется то в порт С записываем все лог.0
{
PORTC &= ~_BV(5);
PORTC &= ~_BV(6);
}
}[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа