USART прерывания и глобальные переменные

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Родился
Сообщения: 14
Зарегистрирован: Чт апр 10, 2014 15:33:44

Сообщение link0ln »

stm32f030/KEIL5
В общем в обработчике прерываний переменная buf_counter должна инкрементироваться, и в итоге в main функции должна отличаться от 0.
Прерывание срабатывает, до инкрементирования код доходит ( можно и buf_counter++, но стоп не поставить тогда ). Но в watch KEILа buf_counter свое значение не меняет!!!
Когда дело доходит до фнукции main buf_counter имеет значение 0.
Я уже всю голову сломал, гугл не помогает. Пробовал уже и переменные по всякому инициализировать, и статическими, и волатильными

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

uint8_t buf[32];
uint8_t buf_counter = 0;
...
void USART1_IRQHandler(void){
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){	
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
        usartData = USART_ReceiveData(USART1);
        if ((usartData =! 13) && (usartData =! 10)){
				buf[buf_counter] = usartData;
				buf_counter += 1;
        }
    }
}

...

void sendstr(){
//функция по отправке по usart данных обратно.
}

...

int main(){
    char buffer[5];
    while(mode == 1){
				sprintf(buffer, "%d", buf_counter);
				sendstr(buffer);
				Delay_ms(10000);
		}
}
Куда копать, что делаю не так?
Реклама
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Сообщение balmer »

Слово volatile должно помочь. Дело в том, что при оптимизации компилятор вполне может решить, что переменная buf_counter не меняется внутри функции main.
Реклама
Родился
Сообщения: 14
Зарегистрирован: Чт апр 10, 2014 15:33:44

Сообщение link0ln »

balmer писал(а):Слово volatile должно помочь.
Кричал при компиляции уже не раз. Не помогает :dont_know:
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Сообщение balmer »

Да, невнимательно прочитал :( Кстати функция приемки "не очень". Надо бы проверять на размер массива, чтобы не переполнилось.
Реклама
Эиком - электронные компоненты и радиодетали
Родился
Сообщения: 14
Зарегистрирован: Чт апр 10, 2014 15:33:44

Сообщение link0ln »

Не знаю что было, переписал строку условия точно так же, и все заработало. Может быть из-за копипаста было что-то не так.
Столкнулся с другой проблемой.
В прерывании по получению байта выполняю сравнение строк при получении символа конца строки. В итоге контроллер видимо захлебывается и не все данные может обработать. СОбсно как лучше поступить?
Реклама
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Сообщение balmer »

Тут надо более полно описать задачу. Я например делаю протокол таким образом, чтобы был "Запрос"-"Ответ". И пока ответа от устройства не пришло, новые данные не посылаются.

Еще достаточно стандартный вариант такой - есть два буфера для данных. В прерывании пишем в один из буферов, когда дошли до окончания пакета (конца строки), то начинаем писать в другой буфер и выставляем флаг, что первый буфер заполнен. Обработка происходит не в прерывании, а в main(). Чуть посложнее сделать циклический буфер.
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2029
Зарегистрирован: Сб ноя 15, 2008 10:09:56
Откуда: г. Тула

Сообщение IfoR »

Не =!, а !=.
Фактически ты ему задал условие такое:

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

(usartData = !13) && (usartData = !10)
Т.е. ты пытаешься присвоить переменной usartData значение !13 = !true = false, а потом !10 = !true = false и в итоге приходим к условию

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

 false && false = false
Соотвтственно, компилятор справедливо считает, что такое условие всегда ложно и вырезает этот код, который никогда не выполнится.
А так же он должен заботливо ответить ворнингом, что данное условие никогда не равно истинне и этот код он вырезает, но оставляет операцию usartData = 0. :)

Кстати, вряд ли от захлебнётся всего лишь от сравнения строк. Скорее всего организация приёмо-передачи страдает. Будет неплохо посмотреть на проблемный код.
Изображение
/dev/urandom - гигабайты информации.

OS: openSUSE 13.2 (x86_64)
Контактная информация:
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Сообщение balmer »

IfoR писал(а):Не =!, а !=.
Вау :))) Я бы такую опечатку наверно только дебагером смог найти.
Родился
Сообщения: 14
Зарегистрирован: Чт апр 10, 2014 15:33:44

Сообщение link0ln »

Спасибо, IfoR. Но, как я уже описал, видимо второй раз переписывая код вручную, видимо машинально правильно написал :)
balmer писал(а):Тут надо более полно описать задачу. Я например делаю протокол таким образом, чтобы был "Запрос"-"Ответ". И пока ответа от устройства не пришло, новые данные не посылаются.
Согласен, вариант стабильный. Я продумывал более адаптивный вариант. А что, если ответ по какой-либо причине не придет, получается контроллер будет вечно ждать. Надо вводить дополнительный таймер, который будет ждать, пока ответ не придет. Если не пришел, либо начинаем все сначала, либо перепосылаем команду. Ну и по сути можно ввести каунтер ошибок, при переполнении которого бы, было сообщено.
balmer писал(а):Еще достаточно стандартный вариант такой - есть два буфера для данных. В прерывании пишем в один из буферов, когда дошли до окончания пакета (конца строки), то начинаем писать в другой буфер и выставляем флаг, что первый буфер заполнен. Обработка происходит не в прерывании, а в main(). Чуть посложнее сделать циклический буфер.
Помойму достаточно передать буфер, в который пушим данные с UART, в функцию, в которой он просто будет скопирован в аналогичный для дальнейшей обработки. Я думаю, что даже при максимальных скоростях UART, коллизий возникнуть не должно, когда буфер бы не успел скопироваться при частоте МК больше нескольких МГц. У меня так работает пока без косяков.
Ответить

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