CodeVision AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

народ помогите норм сделать меню чтобы не висло, а то ввожу комманду c знаками и буквами в конце и он её не выполняет, например fdgdf+CMTI:dfsgdfg и всё оно в ступоре. собственно помогите сделать фильтр чтобы бралась тока комманда на выполнение после чего читалась месага и кидалась на юарт процу read: на выполнение другой команды read

Код: Выделить всё

void sms_read(){
printf("AT+CMGF=1\r"); //set text mode
printf("AT+CMGL\r"); //read all unreaded SMS
}
void activeCommand(char c[])
{  
if (c[0]=='+'&&c[1]=='C'&&c[2]=='M'&&c[3]=='T'&&c[4]=='I')
   {
   sms_read();  
   } 
if (c[0]=='R'&&c[1]=='E'&&c[2]=='A'&&c[3]=='D')
   {
   read();  
   } 
                    
}

unsigned char COMMAND[5];
unsigned int i = 0;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{                                                                 
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) {

WDTCSR = (1<<WDCE) | (1<<WDE);
/* Выкл. сторожевого таймера */
WDTCSR = 0x00;

if (data != ':')  
   {
   COMMAND[i] = data;
   i++;  
   }
else
   { 
   COMMAND[i] = data;
   i = 0;
   activeCommand(COMMAND);
   }
}
#pragma optsize-
#asm("wdr")
WDTCSR=0x39;
WDTCSR=0x29;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif  
}
Реклама
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

не уж то не кто не поможет, выручите господа.
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

kotriks писал(а):не уж то никто не поможет, выручите господа.
Во первых причем тут CVAVR? Кроме того, что программа пишется для этого компилятора никакой связи в вопросе не прослеживается.
Во вторых непонятно что вы подразумеваете под словами
чтобы бралась токалько комманда на выполнение после чего читалась месага и кидалась на юарт
Что откуда приходит, что считается сообщением и куда должна браться команда?
По вашему коду не понятно что вам нужно ведь он у вас не работает.


PS.Вам нужно использовать функции сравнения строк вместо ваших if (c[0]=='R'&&c[1]=='E'&&c[2]=='A'&&c[3]=='D')
Контактная информация:
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

Да знал бы как не спрашивал!
(чтобы бралась только команда на выполнение после чего читалась месага и кидалась на юарт )
это значит что в месаге пришло READ и только его выплёвывало бы в юарт из сообщения всё что вне сообщения отсеивалось.
Реклама
Эиком - электронные компоненты и радиодетали
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

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

С какого символа вообще начинается сообщение? От него и плясать после него значит нулевой элемент сообщения. Далее принимаем все символы этого сообщения, далее выделяем пришедшую команду с помощью функции сравнения строк либо через определенный символ.


PS. Вообще я так пригляделся, вы пишете в массив из пяти элементов символы после двоеточия, но нигде нет проверки на переполнение массива. Остерегайтесь таких ситуаций в коде.
Объявление переменных не ограничивает использование кодексов массива, а лишь выделяет необходимое количество памяти под них. Если попытаетесь записать в COMMAND[6] он запишет и другие данные, которые там находились будут повреждены. ведь 6 это всего лишь смещение от начального указателя на массив.
Контактная информация:
Реклама
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

Сообщение kotriks »

к чему разводить демагогию? если вы можете то покажите на готовом примере.
если делать так

Код: Выделить всё

char buffer[10];
int Count;
buffer[Count] = '\n';
     if( strcmp( buffer, "READ" ) == 0 )
{
read();  
}
как его воткнуть и куда? в while(1) нельзя у меня там другой код выполняется циклично.
Реклама
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1451
Зарегистрирован: Пт фев 19, 2010 19:39:28
Откуда: Москва

Сообщение Сериг »

kotriks,запусти таймер,делай цикл который написал в прерывании по таймеру,8-ми битного тут хватит.
P.S. (Вот и я в дискуссию ворвался :))) )
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

kotriks писал(а):

Код: Выделить всё

char buffer[10];
int Count;
buffer[Count] = '\n';
     if( strcmp( buffer, "READ" ) == 0 )
{
read();  
}
как его воткнуть и куда? в while(1) нельзя у меня там другой код выполняется циклично.
Да хоть куда его воткните, в таком виде работать не будет.
Сначала присваиваете буферу значение, потом сравниваете лучше, наверно так?
buffer[++Count] = '\n'; Так добавится завершающий символ. Вместо вашего варианта, в котором произойдет замещение последнего символа.

PS. Демагогию тут другие люди разводят, те, которые вопрос не могут правильно поставить, и приходится две страницы клещами вытаскивать.
Напишите нормально словами тех. задание, может кто и подберет для вас код из своих работ.
Я лично до сих пор слабо представляю что вы вообще там делаете.
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 88
Зарегистрирован: Вс окт 30, 2011 22:52:51

Сообщение servo »

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

Код: Выделить всё

//Инициализация
EICRA=0x00;EICRB=0x00;EIMSK=0x02;EIFR=0x02;

Код: Выделить всё

//прерывание на INT1
interrupt [EXT_INT1] void ext_int1_isr(void)
{
count++;
}
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

А чем не нравится режим прерывание по переходу на низкий уровень? прерывание по низкому нужно только для того, чтобы МК проснулся, далее уже можно переключиться на любой желаемый режим.
Контактная информация:
Родился
Сообщения: 7
Зарегистрирован: Пн апр 01, 2013 15:40:59
Re:

Сообщение PabloVed »

Еще раз прошу прощения за беспокойство.
Я уже писал в эту тему с проблемой, связанной с моими кривыми лапами.
Спойлер
PabloVed писал(а):Доброго времени суток.

Пишу в связке CodeVisionAVR + Proteus 7 программу для вентильного двигателя (он же BLDC). С датчиками Холла, с прерываниями, с даташитом avr492.
В качестве контроллера выбрал Atmega8. И тут такая проблема - не уверен, что правильно написал прерывание. В целях проверки, изменил код так, что у меня что приходит с датчиков Холла (PINC), то и должно выдаваться на обмотки (PORTD). И получается какая-то ерунда, при симуляции в протеусе показывает что на выход идет только сигнал с PORTD.0

Ткните носом, где я так напортачил, прошу.

Код: Выделить всё

#include <mega8.h>

//unsigned char tmp=0;
//  char flag=1;  
 
void port_init()
{DDRD=1;
 PORTD=1;
 DDRC=0;
 PORTC=0xFF;
 DDRB=0;
 PORTB=0xFF;
}

void timer_init()
{ 
TCCR2=0x01;
TIMSK=0x40;
TCNT2=0x30;
}

void pwm_init() 
{   OCR2=0x00;
 // TCCR2=(1<<COM21)|(1<<WGM20)|(1<<WGM21)|(1<<CS20);
};

interrupt [TIM2_OVF] void overflow_timer2 (void)
{ 
char tmp;
tmp = PINC;
PORTD = tmp;
#asm("sei")
/*switch (tmp)
{
case 0b00000101: {PORTD=0b00000101;}break;   
case 0b00000001: {PORTD=0b00001001;}break;
case 0b00000011: {PORTD=0b00011000;}break;
case 0b00000010: {PORTD=0b00010010;}break;
case 0b00000110: {PORTD=0b00100010;}break;
case 0b00000100: {PORTD=0b00100001;}break;
}*/ 
}   


void main()
{

port_init();
timer_init();
pwm_init();
#asm("sei")
while (1)
{};
}
Посоветовали сменить настройку PORTD. Настройку поменял ( DDRD=0xFF; PORTD - удалил из инициализации), в качестве теста запустил с присвоением, PORTD=PINC (что пришло с датчиков Холла, то и ушло на выход), работает - привод вращается, сигналы принимаются/выдаются.
Но при попытке завести все это через switch - ничего не происходит. В чем может быть проблема?
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

Тут дело скорее даже не в том, что switch используется. Когда нужно, чтобы действовали только несколько бит из всего порта нужно использовать маску вроде такой

Код: Выделить всё

 { 
#define MASK 0b00000111
char tmp;
tmp = PINC&MASK;
#asm("sei")
switch (tmp)
{  
Ведь у вас в настройках выставлено DDRC=0;
PORTC=0xFF;
это значит по умолчанию на неиспользуемых ножках порта будет 1, значит условие case 0b00000101: никогда не выполнится, как и все остальные.
Подучите побитовые операции и все получится.

и как это у вас все вращается, когда всего одна ножка порта используется как выход?

Код: Выделить всё

 {DDRD=1;
 PORTD=1;  
Может нужно так?

Код: Выделить всё

 {DDRD=0xFF;
 PORTD=0x01;  
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

servo писал(а):прерывание срабатывает несколько раз и инкрементирует переменную пока уровень на ноге не будет высоким.
Это заблуждение. Прерывание срабатывает только по перепаду уровня.
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

Это кто вам такое сказал? В AVR Есть несколько режимов прерывания, по спаду, по фронту, по низкому уровню(в дш это level interrupt).
Так вот нужно просто настроить прерывание на спад и все будет ОК.
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 88
Зарегистрирован: Вс окт 30, 2011 22:52:51

Сообщение servo »

vitalik_1984 писал(а):Это кто вам такое сказал? В AVR Есть несколько режимов прерывания, по спаду, по фронту, по низкому уровню(в дш это level interrupt).
Так вот нужно просто настроить прерывание на спад и все будет ОК.
попробовал настроить прерывания по спадающему фронту.. работает.. спасибо !


я вот подумал, может есть такая возможность в AVR чтобы можно было вызывать прерывания программно :)
т.е отсчитал например в основном цикле кол-во входящих импульсов далее запустил прерывание, и считай импульсы не пропуская ни одного импульса, пока выполняется код в прерывании.
Родился
Сообщения: 7
Зарегистрирован: Пн апр 01, 2013 15:40:59

Сообщение PabloVed »

Спойлер
vitalik_1984 писал(а):Тут дело скорее даже не в том, что switch используется. Когда нужно, чтобы действовали только несколько бит из всего порта нужно использовать маску вроде такой

Код: Выделить всё

 { 
#define MASK 0b00000111
char tmp;
tmp = PINC&MASK;
#asm("sei")
switch (tmp)
{  
Ведь у вас в настройках выставлено DDRC=0;
PORTC=0xFF;
это значит по умолчанию на неиспользуемых ножках порта будет 1, значит условие case 0b00000101: никогда не выполнится, как и все остальные.
Подучите побитовые операции и все получится.
Да, в этом и была ошибка. После добавления маски по первым трем битам все заработало. Большое спасибо за помощь!
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

vitalik_1984 писал(а):Это кто вам такое сказал?
Всегда думал, что так и есть. Да и логика моя мне подсказывает, что прерывание по уровню - ненужная и глупая фича. Даже не укладывается в голове куда можно её применить :roll:
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

servo писал(а):попробовал настроить прерывания по спадающему фронту.. работает.. спасибо !

Рад, что помог :))
servo писал(а):
я вот подумал, может есть такая возможность в AVR чтобы можно было вызывать прерывания программно :)
т.е отсчитал например в основном цикле кол-во входящих импульсов далее запустил прерывание, и считай импульсы не пропуская ни одного импульса, пока выполняется код в прерывании.
ничего не понял, зачем вам в основном цикле считать? у вас все прекрасно в прерывании считается, можно при желании в самом прерывании устанавливать глобальные флаги для того, чтобы отслеживать какие либо события в основном цикле.
А чтобы можно было вызвать еще и программно то, что выполняется в прерывании можно просто оформить в функции и вызывать ее при необходимости либо в основном, либо из прерывания.
Только так, чтобы эта функция не была затратна по времени.
Даже не укладывается в голове куда можно её применить
Просто когда Мк просыпается только от этого прерывания его просто приходится применять :)))
Есть еще, конечно вариант с прерыванием по изменению уровня( pin change), но оно, как я понял, не у всех Мк бывает.
Контактная информация:
Потрогал лапой паяльник
Сообщения: 349
Зарегистрирован: Пн ноя 29, 2010 05:52:05
Откуда: Иркутск

Сообщение Импульс »

Здравствуйте! 8)

Много прочитал информации про:
Прерывания (INTERRUPTS)
Таймеры/счетчики (TIMER/COUNTERS)
И теперь понятно ,что не чего не понятно :cry: .
Теперь знаю:
в МК все прерывания —
аппаратные, и делятся они нa
• внутренние
• внешние (пока не интерисуют)
далее>>

для запуска инициализации любого прерывания надо в программе сделать :
1. разрешить прерывания вообще (по умолчанию они запрещены),
2. затем разрешить это конкретное прерывание,
3. установить для него один из доступных режимов и, наконец,
4. установить вектор прерывания:

или так >>

a) обработка прерываний была разрешена,
b) отслеживалось переполнение таймера, и
c) существовала программа обработки прерывания по переполнению таймера.

и то от чего может происходить прерывание:

1. от таймеров,
2. от аналогового компаратора,
3. от последовательного порта и т.д.
:roll:

чуть не забыл
про 4 главных регистра:

- GIMSK (General Interrupt Mask Register) - разрешает или запрещает внешние прерывания по входу INT0/INT1;
- GIFR (General Interrupt Flag Register) - регистр флагов внешних прерываний;
- TIMSK (Timer/Counter Interrupt Mask Register) - регистр маскирования прерываний от таймера/счетчика Т/С0 и Т/С1;
- TIFR (Timer/Counter Interrupt Flag Register) - регистр флагов прерываний от таймеров/счетчиков.

А как теперь это связать :facepalm: не знаю...
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

И причём тут CV AVR ?
Контактная информация:
Ответить

Вернуться в «AVR»