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

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

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

Сообщение 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 
}
kotriks
Грызет канифоль
Сообщения: 274
Зарегистрирован: Чт апр 28, 2011 15:08:58

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

Сообщение kotriks »

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

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

Сообщение vitalik_1984 »

kotriks писал(а):не уж то никто не поможет, выручите господа.

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

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


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

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

Сообщение kotriks »

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

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

Сообщение vitalik_1984 »

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

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


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

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

Сообщение kotriks »

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

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

char buffer[10];
int Count;
buffer[Count] = '\n';
     if( strcmp( buffer, "READ" ) == 0 )
{
read(); 
}

как его воткнуть и куда? в while(1) нельзя у меня там другой код выполняется циклично.
Аватара пользователя
Сериг
Это не хвост, это антенна
Сообщения: 1451
Зарегистрирован: Пт фев 19, 2010 19:39:28
Откуда: Москва

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

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

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

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

Сообщение vitalik_1984 »

kotriks писал(а):

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

char buffer[10];
int Count;
buffer[Count] = '\n';
     if( strcmp( buffer, "READ" ) == 0 )
{
read(); 
}

как его воткнуть и куда? в while(1) нельзя у меня там другой код выполняется циклично.

Да хоть куда его воткните, в таком виде работать не будет.
Сначала присваиваете буферу значение, потом сравниваете лучше, наверно так?
buffer[++Count] = '\n'; Так добавится завершающий символ. Вместо вашего варианта, в котором произойдет замещение последнего символа.

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

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

Сообщение servo »

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

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

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


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

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

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

Сообщение vitalik_1984 »

А чем не нравится режим прерывание по переходу на низкий уровень? прерывание по низкому нужно только для того, чтобы МК проснулся, далее уже можно переключиться на любой желаемый режим.
PabloVed
Родился
Сообщения: 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 - ничего не происходит. В чем может быть проблема?
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение 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;  
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

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

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

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

Сообщение vitalik_1984 »

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

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

Сообщение servo »

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


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


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

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

Сообщение PabloVed »

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

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

 { 
#define MASK 0b00000111
char tmp;
tmp = PINC&MASK;
#asm("sei")
switch (tmp)
{
  

Ведь у вас в настройках выставлено DDRC=0;
PORTC=0xFF;
это значит по умолчанию на неиспользуемых ножках порта будет 1, значит условие case 0b00000101: никогда не выполнится, как и все остальные.
Подучите побитовые операции и все получится.

Да, в этом и была ошибка. После добавления маски по первым трем битам все заработало. Большое спасибо за помощь!
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

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

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

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

Сообщение vitalik_1984 »

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

Рад, что помог :))
servo писал(а):
я вот подумал, может есть такая возможность в AVR чтобы можно было вызывать прерывания программно :)
т.е отсчитал например в основном цикле кол-во входящих импульсов далее запустил прерывание, и считай импульсы не пропуская ни одного импульса, пока выполняется код в прерывании.

ничего не понял, зачем вам в основном цикле считать? у вас все прекрасно в прерывании считается, можно при желании в самом прерывании устанавливать глобальные флаги для того, чтобы отслеживать какие либо события в основном цикле.
А чтобы можно было вызвать еще и программно то, что выполняется в прерывании можно просто оформить в функции и вызывать ее при необходимости либо в основном, либо из прерывания.
Только так, чтобы эта функция не была затратна по времени.
Даже не укладывается в голове куда можно её применить

Просто когда Мк просыпается только от этого прерывания его просто приходится применять :)))
Есть еще, конечно вариант с прерыванием по изменению уровня( pin change), но оно, как я понял, не у всех Мк бывает.
Импульс
Потрогал лапой паяльник
Сообщения: 349
Зарегистрирован: Пн ноя 29, 2010 05:52:05
Откуда: Иркутск

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

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

Здравствуйте! 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: не знаю...
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

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

И причём тут CV AVR ?
Ответить

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