Страница 1 из 1

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

Добавлено: Чт дек 18, 2014 15:39:33
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);
		}
}
Куда копать, что делаю не так?

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

Добавлено: Чт дек 18, 2014 16:36:32
balmer
Слово volatile должно помочь. Дело в том, что при оптимизации компилятор вполне может решить, что переменная buf_counter не меняется внутри функции main.

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

Добавлено: Чт дек 18, 2014 16:39:12
link0ln
balmer писал(а):Слово volatile должно помочь.
Кричал при компиляции уже не раз. Не помогает :dont_know:

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

Добавлено: Чт дек 18, 2014 16:47:20
balmer
Да, невнимательно прочитал :( Кстати функция приемки "не очень". Надо бы проверять на размер массива, чтобы не переполнилось.

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

Добавлено: Чт дек 18, 2014 18:06:52
link0ln
Не знаю что было, переписал строку условия точно так же, и все заработало. Может быть из-за копипаста было что-то не так.
Столкнулся с другой проблемой.
В прерывании по получению байта выполняю сравнение строк при получении символа конца строки. В итоге контроллер видимо захлебывается и не все данные может обработать. СОбсно как лучше поступить?

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

Добавлено: Чт дек 18, 2014 22:54:20
balmer
Тут надо более полно описать задачу. Я например делаю протокол таким образом, чтобы был "Запрос"-"Ответ". И пока ответа от устройства не пришло, новые данные не посылаются.

Еще достаточно стандартный вариант такой - есть два буфера для данных. В прерывании пишем в один из буферов, когда дошли до окончания пакета (конца строки), то начинаем писать в другой буфер и выставляем флаг, что первый буфер заполнен. Обработка происходит не в прерывании, а в main(). Чуть посложнее сделать циклический буфер.

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

Добавлено: Чт дек 18, 2014 23:21:12
IfoR
Не =!, а !=.
Фактически ты ему задал условие такое:

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

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

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

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

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

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

Добавлено: Пт дек 19, 2014 11:04:41
balmer
IfoR писал(а):Не =!, а !=.
Вау :))) Я бы такую опечатку наверно только дебагером смог найти.

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

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