Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту


 
Опции темы
Непрочитано 01.04.2017, 01:34  
supercelt
Прописка
 
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
supercelt на пути к лучшему
По умолчанию Глюк приёма данных по USART

Всем доброй ночи! Я недавно создавал тему тут о времени приёма байта по usart. И этот вопрос вытекает как бы из того вопроса. Но я подумал лучше создать отдельную тему, что бы не было путаницы.

Ну, тут я принимаю от gsm модема периодические ответы. А именно звонок. Посылка данных выбрасывается в usart с интервалом в 5 секунд, это как раз те самые гудки, которые вы слышите на той стороне.

Значит посылка данных при звонке выглядит точно вот так:

Нажмите на изображение для увеличения
Название: 6bc32c3fe7c5.png
Просмотров: 0
Размер:	59.6 Кб
ID:	112556


на картинке 7 посылок, ну то есть было 7 гудков дозвона. Цифры номера замазал, на всякий случай, не к чему он тут)).

вобщем это приём в терминале. И как всегда проблема, когда приёмом занимается МК. Уже полночь и я абсолютно полностью не могу врубиться что у меня не так, хотя мне кажется дело как всегда в какой-нибудь мелкой лаже. Ну так вот. Запускаю отадку в Keil, звоню, смотрю в инспектор переменных. В нём я вижу что каждый раз набивается в буфер при посылке данных.

Абсолютно рандомно эти данные благополучно съезжают. А выглядит это вот так:

Нажмите на изображение для увеличения
Название: 04578061be1d.png
Просмотров: 0
Размер:	128.9 Кб
ID:	112555


То есть часть данных просто берёт и перезаписывается поверх уже существующих в начало. Причём как я уже говорил происходит это рандомно. Бывает при первом гудке, бывает набьётся с 4 гудка,
бывает со 2. Причём я попробовал оставить только одну процедуру набива, закомментив строку Flag_receive_complete = 1; То есть просто, посылка пришла, смотрю что в буфере, далее процедура повторяется.
Ещё пробовал ставить наивысший приоритет прерывания у usart. Так как у меня ещё в проге тикает RTC и пара таймеров. Один из них уходит в прерывание каждые 6 сек. Но я так понял что это особо не влияет.

Ах да... мк stm32f100ret6b, F = 24 MHz

Код:

Код:
#include "gsm.h"
#include "lcd.h"
#include ‹string.h›
#define BUFFER_RECEIVE_SIZE 50
char Buffer_receive[BUFFER_RECEIVE_SIZE] = "\0";
uint8_t i = 0, Flag_receive_complete = 0;
void GSM_INI(void){
//USART1
		RCC-›APB2ENR |= RCC_APB2ENR_USART1EN;                           					//Вкл. тактирование USART1.
		RCC-›APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN;        					//Вкл. тактирование порта А и альтернативной функции выводов.
		GPIOA-›CRH &= ~GPIO_CRH_CNF9_0;														//Сброс бита CNF9_0, так как он делает вывод плавающим входом.
		GPIOA-›CRH |= GPIO_CRH_CNF9_1; 														//Режим вывода в альтернативную функцию, выход с подтяжкой.
		GPIOA-›CRH |= GPIO_CRH_MODE9_1; 													//Скорость выхода 2 МГц.
		USART1-›BRR = 0x9C4;                                            					//9600 бод скорость обмена USART
		USART1-›CR1 |= USART_CR1_RXNEIE;                                					//Разрешаем локальные прерывания по приёму USART
		USART1-›CR1 |= USART_CR1_IDLEIE; 													//Включаем прерывания по IDLEIE (завершение приёма строки).
		USART1-›CR1 |= USART_CR1_RE | USART_CR1_TE;                     					//Включаем передатчик и приёмник
		NVIC_EnableIRQ(USART1_IRQn);                                    					//Разрешаем глобальные прерывания для USART1
		USART1-›CR1 |= USART_CR1_UE;                                    					//Включаем USART
}		

void USART1_IRQHandler(void){ 																//Обработчик прерываний USART1.
		if(USART1-›SR & USART_SR_RXNE){ 													//Если прерывание вызвано по завершению приёма 1 байта.
				USART1-›SR &= ~USART_SR_RXNE; 												//Сбрасываем флаг приёма 1 байта.
				Buffer_receive[i++] = USART1-›DR;											//Записываем в i-ы элемент массива принятый байт.
		}
		if(USART1-›SR & USART_SR_IDLE){														//Если прерывание вызвано по завершению приёма строки (реализовано аппаратно по флагу IDLE).
				(void)(USART1-›DR & 0xFF);                                   			    //Читаем геристр DR что бы сбросился бит IDLE.
				i = 0;
				Flag_receive_complete = 1;													//Ставим флаг, что готовы обработать набитый массив.
		}
}
Может это IDLE глючит?... Хотя оно же срабатывает когда линия свободна...А после посылки у меня 5-6 сек тишины... времени достаточно.. хммм...
Реклама:
supercelt вне форума  
Непрочитано 01.04.2017, 02:18  
mike-y-k
Модератор
 
Регистрация: 04.08.2010
Адрес: Москва СЗАО
Сообщений: 11,257
Сказал спасибо: 11,170
Сказали Спасибо 3,858 раз(а) в 2,928 сообщении(ях)
mike-y-k на пути к лучшему
По умолчанию Re: Глюк приёма данных по USART

Картинки можно убрать в спойлеры, тогда разметка не пострадает. И лучше таки с рекламой, а не с такими простынями.
Да и их содержимое вполне можно текстом описать. Листать такие простыни не самое приятное из доступных удовольствий, а на мелком тексте ещё и глаза жалко.
Ну и в продолжение к предыдущей Вашей теме - у Вас классический UART и никакого USART. Поменяйте таки названия на соответствующие действительности. Инструкция в разделе о форуме, даже в ЛС писал Вам ссылку.

PS обычная putty умеет писать журнал соединения в обычный файл и нет нужды в первой картинке.
Для второй тоже достаточно просто содержимого буфера с комментариями.
Конечно это требует некоторых телодвижений, но от них есть и польза - в процессе иногда приходит озарение по причине ошибки.
__________________
rtfm forever должно быть основой для каждого. Альтернатива грустна, поскольку метод слепого щенка успешно работает при весьма малом числе вариантов…

Последний раз редактировалось mike-y-k; 01.04.2017 в 02:27.
mike-y-k вне форума  
Непрочитано 01.04.2017, 05:30  
H4LF
Вид на жительство
 
Аватар для H4LF
 
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
H4LF на пути к лучшему
По умолчанию Re: Глюк приёма данных по USART

Ну если рандомно, то, видимо, что-то рандомно портит переменную i.
Я бы настоятельно рекомендовал быть поосторожнее с глобальными переменными, тем более однобуквенными, тем более с i.
Можно оставить i, но объявить её в обработчике прерывания (в котором она используется) как:
Код:
static uint8_t i = 0;
Хотя если я не ошибаюсь локальные статики и так инициализируются нулём.
А вообще - я бы советовал использовать кольцевой буфер для этого дела.
Ещё нужно посмотреть (если ещё не) - IDLE точно срабатывает когда надо, а не посреди передачи? Эх и не надёжно это... но это не к этой теме - хотите делать так - делайте.
Ну и ещё пару замечаний:
Код:
USART1-›SR &= ~USART_SR_RXNE;
тут & не нужен. В этом регистре флаги сбрасываются записью нуля. запись единицы ничего не меняет. А конкретно этот флаг сбрасывается чтением из USART1-›DR. Так что отдельный сброс этого флага вообще не нужен в этом случае.
Не совсем понял, что это:
Код:
(void)(USART1-›DR & 0xFF);
Чтение из регистра USART1-›DR после чтения USART1-›SR для сброса флага IDLE?
H4LF вне форума  
Непрочитано 01.04.2017, 09:38  
NewWriter
Заблокирован
 
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,220 раз(а) в 1,319 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию Re: Глюк приёма данных по USART

Сообщение от mike-y-k Посмотреть сообщение
классический UART и никакого USART. Поменяйте таки названия на соответствующие действительности
Нинада Модуль зовется USART, и евойный хэндлер тоже зовется USART1_IRQHandler, другое название просто не будет принято (много где переименовывать придется).
А по поводу рандомной перезаписи - у вас индекс буфера - i, глобальная. Вы уверены, что больше нигде эта глобальная i не изменяется случайно?

Последний раз редактировалось NewWriter; 01.04.2017 в 09:40.
NewWriter вне форума  
Непрочитано 01.04.2017, 10:15  
dgrishin
Почётный гражданин KAZUS.RU
 
Регистрация: 12.02.2013
Сообщений: 1,038
Сказал спасибо: 43
Сказали Спасибо 273 раз(а) в 214 сообщении(ях)
dgrishin на пути к лучшему
По умолчанию Re: Глюк приёма данных по USART

Вот где собака порылась
void USART1_IRQHandler(void){ //Обработчик прерываний USART1.
if(USART1-›SR & USART_SR_RXNE){ //Если прерывание вызвано по завершению приёма 1 байта.
USART1-›SR &= ~USART_SR_RXNE; //Сбрасываем флаг приёма 1 байта.
Buffer_receive[i++] = USART1-›DR; //Записываем в i-ы элемент массива принятый байт.
}
if(USART1-›SR & USART_SR_IDLE){ //Если прерывание вызвано по завершению приёма строки (реализовано аппаратно по флагу IDLE).
(void)(USART1-›DR & 0xFF); //Читаем геристр DR что бы сбросился бит IDLE.
i = 0;
Flag_receive_complete = 1; //Ставим флаг, что готовы обработать набитый массив.
}
}

после обработки условия if(USART1-›SR & USART_SR_RXNE) надо выходить из обработчика (return), в вы начинаете проверять условие if(USART1-›SR & USART_SR_IDLE) - и ловите момент когда USART IDLE - это нестабильный код и периодически переменная i обнуляется.
dgrishin вне форума  
Непрочитано 01.04.2017, 10:36  
dgrishin
Почётный гражданин KAZUS.RU
 
Регистрация: 12.02.2013
Сообщений: 1,038
Сказал спасибо: 43
Сказали Спасибо 273 раз(а) в 214 сообщении(ях)
dgrishin на пути к лучшему
По умолчанию Re: Глюк приёма данных по USART

Сообщение от NewWriter Посмотреть сообщение
Извиняюсь, ваапще-то и без того выходит оттудава - по закрытию скобки }
А в функции, которая имеет тип позвращаемого агрумента void, return как бы и не нужен, при компиляции даже предупреждение выдаст.
Да, код будет отрабатываться весь до скобки, завершающей обработчик -
то есть до
}
} ‹-

А команда return без переменной - это просто выход из обработчика.
Если она вас смущает, тогда
goto EXIT; после первого if

}
:EXIT;
}
dgrishin вне форума  
Непрочитано 01.04.2017, 21:26  
supercelt
Прописка
 
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
supercelt на пути к лучшему
По умолчанию Re: Глюк приёма данных по USART

Сообщение от H4LF Посмотреть сообщение
Чтение из регистра USART1-›DR после чтения USART1-›SR для сброса флага IDLE?
Так точно!
Попробовал сделать вот так:

Код:
void USART1_IRQHandler(void){ 																				
static uint8_t k;	
if(USART1-›SR & USART_SR_RXNE){ 	
Buffer_receive[k] = USART1-›DR;																			
k++;
return;
}
}
без всяких idle, просто тупо набив буфера. Даже i сменил на k, k - нигде больше не используется. И опять такая же рандомная фигня. Один в один((( По логике получается что в момент приёма как бы кривой посылки, прерывание usart не срабатывает, а начинает срабатывать только с 31 символа. И что интересно, ни символом до ни после, именно с 31-ого.
supercelt вне форума  
Непрочитано 02.04.2017, 01:25  
H4LF
Вид на жительство
 
Аватар для H4LF
 
Регистрация: 10.06.2007
Сообщений: 429
Сказал спасибо: 34
Сказали Спасибо 51 раз(а) в 47 сообщении(ях)
H4LF на пути к лучшему
По умолчанию Re: Глюк приёма данных по USART

Сообщение от supercelt Посмотреть сообщение
И что интересно, ни символом до ни после, именно с 31-ого.
Так рандомно или что-то именно с 31?
Мне совсем не верится, что это посылка кривая... Скорее софт в камне кривой.
Переменная счётчика в памяти расположена скорее всего после буфера. Как и флаг завершения приёма. А в С отсутствует проверка границ массива(контроль границ на программисте). Не наезжает ли буфер на свой же счётчик, таким вопросом задался я. Без сброса счётчика и за больше одного звонка - точно выкатывается за свой размер. Проверьте это первым делом, это можно сделать и увеличив буфер до 256 элементов, при счётчике uint8_t точно не переполнится (но пойдёт записывать по второму разу).
H4LF вне форума  
Непрочитано 02.04.2017, 02:12  
supercelt
Прописка
 
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
supercelt на пути к лучшему
По умолчанию Re: Глюк приёма данных по USART

Рандомно происходит сбой, то есть либо с первого звонка сразу, либо с 3, либо со 2. Но постоянно то, что строка переламывается между символами 9 и ". То есть на 31 символе. Так вот. Увеличил буфер до 254. Сделал так:
Код:
void USART1_IRQHandler(void){
		//static uint8_t k;
		if(USART1-›SR & USART_SR_RXNE){
				//USART1-›SR &= ~USART_SR_RXNE;
				Buffer_receive[k] = (USART1-›DR & 0xFF);
				k++;
			return;
		}
}
Записывается норм, до конца массива без накладок.

Но мне то надо узнать что строка передана. Поэтому делаю так:

Код:
void USART1_IRQHandler(void){
		//static uint8_t k;
		if(USART1-›SR & USART_SR_RXNE){
				//USART1-›SR &= ~USART_SR_RXNE;
				Buffer_receive[k] = (USART1-›DR & 0xFF);
				k++;
			return;
		}
		if(USART1-›SR & USART_SR_IDLE){
				(void)(USART1-›DR & 0xFF);//Buffer_receive[i++] = USART1-›DR;
				k = 0;
				//Receive_complete = 1;
				return;
		}
}
И вот тут мне попался момент, когда сбой произошёл при 1 звонке. Массив записался до 31 символа, а далее всё остальное записалось поверх в начало. Из чего следует вывод, что IDLE срабатывает почему-то раньше. И рандомно. Возникает вопрос, зачем тогда это idle надо, если оно так криво работает. И всё ещё остался главный вопрос. Как всё-таки гарантировано определить, что вся строка передана, исходя из того, что маркеров конца - нет, и длина строки заранее неизвестна.

Подумал я подумал и решил поставить DMA и на приём. На передаче оно у меня уже есть. Но DMA подразумевает, что размер передаваемых данных известен заранее. Если при передаче strlen рулит, то тут так не прокатит. Я попробовал поставить 50, как и приёмный буфер. Пишется в массив всё замечательно, НО, флаг завершения передачи ставится только после 2 звонка. Потому что при 1 звонке заполняется не весь буфер. А мне бы только 1 раз наполнить буфер от 1 звонка и дальше выключить DMA. Получается DMA тоже как бы не катит.
supercelt вне форума  
Непрочитано 02.04.2017, 02:17  
supercelt
Прописка
 
Регистрация: 29.03.2007
Сообщений: 185
Сказал спасибо: 11
Сказали Спасибо 1 раз в 1 сообщении
supercelt на пути к лучшему
По умолчанию Re: Глюк приёма данных по USART

Ах да, ещё вариант. Прямо в прерывании посимвольно проверять. Но мне кто-то посоветовал сначала набить массив, а потом кромсать его строковыми функциями/

UPD
попробовал убрать idle. Сделал таймер, как было изначально. Настроил на прерывание по переполнению. Взял с запасом 0.5 сек. При прерывании usart каждый раз сбрасываю счётчик этого таймера. По расчётам, после приёма последнего байта проходит 0,5 сек, далее прерывание и ставим флаг конца строки. Но не тут-то было. На 4 звоне опять взял и с 31 символа всё записал поверх в начало(((

Последний раз редактировалось supercelt; 02.04.2017 в 02:53.
supercelt вне форума  
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
FAQ (ЧаВО) по PROTEUS для начинающих и не только dosikus Proteus 221 07.03.2024 22:45
Ускорить компьютер 7Fantomas7 Ремонт оргтехники 111 08.08.2018 05:27
Получение данных по USART Fangir AVR 32 02.12.2014 15:15
Получение данных по USART в CVAVR himik131 Микроконтроллеры, АЦП, память и т.д 6 12.03.2011 00:12
Вопрос по мультипроцессорному обмену USART MEGA8 vikont-s Микроконтроллеры, АЦП, память и т.д 0 10.08.2006 14:55


Часовой пояс GMT +4, время: 23:20.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot