Обсуждаем контроллеры компании Atmel.
Ср дек 14, 2016 11:45:41
Подскажите почему не видит в коде глобальную переменную Danue в среде WinAVR. Что не так делаю. Вот снимок. вот сам код.
Спойлер
/*
* USARTATMEGA8.c
*
*/
#include <avr/io.h>
#define F_CPU 4000000
#define BAUD 9600L // Скорость обмена данными
#define UBRRL_value (F_CPU/(BAUD*16))-1
unsigned char Danue=0;
int main(void)
{
/*Настраиваем соответствующий порт передачи на выход*/
PORTD|=(1<<PD1);
/*Устанавливаем бит разрешение передачи*/
UCSRB|=(1<<TXEN);
//Переходим в регистр UCSRC
UCSRC|=(1<<URSEL);
//Размер передоваемого слова выставляем на 8 бит.*/
UCSRC|=(1<<UCSZ1)|(1<<UCSZ0);
//Выбираем режим работы ассинхронный
UCSRC&=~(1<<UMSEL);
//Проверка на четность выставляем в ноль
UCSRC&=~(1<<UPM1)&(1<<UPM0);
//Количество стоп битов также ставим 1
UCSRC&=~(1<<USBS);
//Устанавливают скорость передачи в бодах
UCSRC&=~(1<<URSEL);//Переходим в регистр UBRR;
UBRRL=UBRRL_value;//Младший бит
UBRRH=0x00;//Старший бит
/*Передаем наши данные через UDR всего один раз. */
//UDR=0x45;
while(1)
{
//Проверяем флаг UDRE — флаг опустошения регистра передатчика,
//устанавливается в 1 при пустом буфере передатчика — UDR значит можно передовать;
if ((Danue==0)&&(UCSRA|(1<<UDRE)))
{ //Отправляем только один раз
Danue++;
UDR=0x45;
}
if ((Danue==1)&&(UCSRA|(1<<UDRE)))
{ //Отправляем только один раз
UDR=0x53;
Danue++;
}
}
}
- Вложения
-
- 8888.png
- (126.03 KiB) Скачиваний: 437
Ср дек 14, 2016 13:00:31
Компилятор при оптимизации увидел, что она фактически не используется, поэтому её выбросил и сгенерировал код наподобие:
- Код:
if (UCSRA | (1<<UDRE))
UDR=0x45;
if (UCSRA | (1<<UDRE))
UDR=0x53;
while(1) {}
Думаю, дело именно в этом.
Ср дек 14, 2016 13:09:14
Подскажите а как мне ее задействовать Danue в условии, так как в отношении этой переменной должно срабатывать условие.
- Код:
if ((Danue==0)&&(UCSRA|(1<<UDRE)))
{ //Отправляем только один раз
Danue=1;
UDR=0x45;
}
Ср дек 14, 2016 13:12:31
WiseLord писал(а):Думаю, дело именно в этом
либо сделал ее регистровой (я не вникал в логику использования переменной).
Добавлено after 1 minute 38 seconds:strengerst писал(а):а как мне ее задействовать Danue в условии
а это на самом деле надо? судя по комментарию вам нужно выдать данные в USART один раз - ну так и выдавайте ВНЕ цикла. будет один раз.
Ср дек 14, 2016 13:15:04
Мне для понимания для себя что бы знать. На коменты не смотрите. Как сделать ее не регистровой.
Ср дек 14, 2016 13:20:18
strengerst писал(а):Как сделать ее не регистровой
сделайте ее static
Ср дек 14, 2016 13:27:36
Не помогло. Делал так
- Код:
static unsigned char Danue=0;
Ср дек 14, 2016 13:44:44
если не помогло, значит, она и в самом деле лишняя по логике работы. можете, конечно, сделать ее volatile, но это тупиковый путь - подгонять работу компилятора под неверную логику программы
Ср дек 14, 2016 13:49:18
Ну я хочу создать условие, в котором переменная принимает те или иные значения и в отношении нее сделать действия, как мне это провернуть.
Спасибо volatile помогло. Пойду по кривой дорожке.
Последний раз редактировалось
strengerst Ср дек 14, 2016 13:52:50, всего редактировалось 1 раз.
Ср дек 14, 2016 13:52:46
В какой-то момент компилятор посчитает нецелесообразным её выбрасывать, и станет всё нормально. Но пока, в таком виде, она не нужна. Ну, или сделайте-таки volatile, на время отладки.
Ср дек 14, 2016 13:53:32
Спасибо volatile помогло.
Подскажите сколько должна быть задержка между оправками данных по USART.
Без задержки я так понимаю отправлять друг за другом данные нельзя пока буфер не очистится.
Если я делаю с задержкой то в терминале протеуса все корректно отображается, а если без нее то только первое условие.
А второе нет.
- Код:
if ((UCSRA||(1<<UDRE))&&(Danue==0))
{ //Отправляем только один раз
UDR=0x45;
Danue++;
}
_delay_ms(1000);
if ((UCSRA||(1<<UDRE))&&(Danue==1))
{ //Отправляем только один раз
UDR=0x53;
Danue++;
}
Ср дек 14, 2016 17:51:07
В даташите приведены функции передачи байта на UART, перед отправкой ожидающие опустошения буфера. Проще говоря, ждут, пока не поднимется флаг UDRE
Чт дек 15, 2016 09:48:36
Спасибо это я понял. но не понятно почему не работает условие без задержки delay. Ну вот код ниже в нем в условии указано что только при опустошении буфера UDRE (то есть когда он в 1 то буфер пуст и данные можно передавать), передать данные UDR=0x45;
и прибавить 1 к переменной Danue. Условие выполняется а вот второе точно такое же условие уже не выполняется. Почему? А вот если поставить между условиями задержку в 1 секунду. Все работает.
Рабочий код
Спойлер
- Код:
if ((UCSRA||(1<<UDRE))&&(Danue==0))
{ //Отправляем только один раз
UDR=0x45;
Danue++;
}
_delay_ms(1000);
if ((UCSRA||(1<<UDRE))&&(Danue==1))
{ //Отправляем только один раз
UDR=0x53;
Danue++;
}
Не рабочий код (Второе условие не передается)
Спойлер
- Код:
if ((UCSRA||(1<<UDRE))&&(Danue==0))
{ //Отправляем только один раз
UDR=0x45;
Danue++;
}
if ((UCSRA||(1<<UDRE))&&(Danue==1))
{ //Отправляем только один раз
UDR=0x53;
Danue++;
}
Весь этот код находиться в цикле while(1) функции int main(void);
Чт дек 15, 2016 09:59:28
strengerst писал(а):но не понятно почему не работает условие без задержки delay
потому что вы ошибаетесь в записи логических выражений.
strengerst писал(а):UCSRA||(1<<UDRE)
вот это выражение истинно ВСЕГДА. изучите битовые манипуляции над переменными, например, вот по этой моей заметке:
http://arv.radioliga.com/content/view/191/49/
Чт дек 15, 2016 10:00:33
Самое лучшее объяснение на примере.
Как проверить установлен ли бит в переменной? Нужно обнулить все биты, кроме проверочного, а потом сравнить полученное значение с нулем
if ((tmp & (1<<2)) != 0 ){
// блок будет выполняться, только если установлен
// второй бит переменной tmp
}
if ((tmp & (1<<2)) == 0 ){
// блок будет выполняться, только если не установлен
// второй бит переменной tmp
}
if ((UCSRA & (1<<UDRE)) != 0 ){
// блок будет выполняться, только если установлен
// UDRE бит переменной tmp
}
if ((UCSRA & (1<<UDRE)) == 0 ){
// блок будет выполняться, только если не установлен
// UDRE бит переменной UDRE=1
}
Или так:
if (~(UCSRA | ~(1<<UDRE))== 0 ){
// блок будет выполняться, только если установлен
// UDRE бит переменной UDRE=1
}
Пт дек 16, 2016 10:35:08
Помогите найти ошибку в приемнике. Почему не выполняется условие if(Zeto==0x56) {PORTD|=(1<<PD5);Zeto++;}
Я понимаю что из-за того что Zeto не равно 0x56. Но почему? Мы ведь считываем данные после отправки с UDR а там точно 0x56?
Спойлер
- Код:
/*
* USARTATMEGA8.c
*
*/
#include <avr/io.h>
#define F_CPU 4000000
#define BAUD 9600L // Скорость обмена данными
#define UBRRL_value (F_CPU/(BAUD*16))-1 //volatile unsigned char Danue=0;
unsigned char Danue=0;
unsigned char Zeto=0;
int main(void)
{
PORTD|=(1<<PD4);
/*Настраиваем соответствующий порт передачи на вход*/
PORTD&=~(1<<PD0);
/*Устанавливаем бит разрешение приема*/
UCSRB|=(1<<RXEN);
//Переходим в регистр UCSRC
UCSRC|=(1<<URSEL);
//Размер принимаемого слова выставляем на 8 бит.*/
UCSRC|=(1<<UCSZ1)|(1<<UCSZ0);
//Выбираем режим работы ассинхронный
UCSRC&=~(1<<UMSEL);
//Проверка на четность выставляем в ноль
UCSRC&=~(1<<UPM1)&(1<<UPM0);
//Количество стоп битов также ставим 1
UCSRC&=~(1<<USBS);
//Устанавливают скорость передачи в бодах
UCSRC&=~(1<<URSEL);//Переходим в регистр UBRR;
UBRRL=UBRRL_value;//Младший бит
UBRRH=0x00;//Старший бит
/*Принимаем наши данные через RXD всего один раз. */
while(1)
{
//Проверяем флаг RXC флаг завершения приема, устанавливается в 1 при наличие непрочитанных данных в буфере приемник — UDR; — флаг опустошения регистра передатчика,
//(UCSRA & (1<<UDRE)) - производит чтение бита.
//UCSRA ^(1<<UDRE) - инверсия.
if ((UCSRA & (1<<RXC))!= 0 ){
if (Danue==0)
{ //Отправляем только один раз
Zeto=UDR;
Danue++;
}}
if(Zeto==0x56)
{PORTD|=(1<<PD5);
Zeto++;
}
}
}
- Вложения
-
- яяяя.png
- (65.45 KiB) Скачиваний: 276
-
- яяя.png
- (30.8 KiB) Скачиваний: 421
Пт дек 16, 2016 11:37:47
Уберите условие if (Danue==0), принимайте данные всегда и весь UDR кидайте в PORTB, так будет нагляднее понять что Вы приняли на самом деле.
Самая распространенная ошибка работы с УАРТ, это не правильная настройка скорости. В протеусе то выставили частоту МК? А может Вы не с теми параметрами отправляете данные?
Пт дек 16, 2016 12:14:43
Да в роде в настройках все правильно поставил. Вот снимок. Подправил код
Спойлер
- Код:
if ((UCSRA & (1<<RXC))!= 0 ){
Zeto=UDR;
}
if(Zeto==0x56)
{PORTD|=(1<<PD5);
Zeto++;
}
- Вложения
-
- pppp.png
- (104.25 KiB) Скачиваний: 426
-
- cccc.png
- (134.55 KiB) Скачиваний: 421
Вс дек 25, 2016 09:00:19
Доброго времени суток.
Столкнулся с проблемой в winavr.
Вот, к примеру, простенькая программа:
Спойлер
- Код:
#include <avr/io.h>
#include <avr/interrupt.h> /* для sei() */
#include <util/delay.h> /* для _delay_ms() */
#define KN_PORT PORTD // порт
#define KN_DDR DDRD
#define KN_PIN PIND
#define KN 0 // пин кнопка
unsigned int last_millis=0;
char i=0;
// Timer 0 overflow interrupt service routine
ISR( TIMER0_OVF_vect )
{
// Reinitialize Timer 0 value
TCNT0=0xB2;
// Place your code here
last_millis++;
}
char skan_klav (char Pin_Set, volatile char *PORT_set) {
last_millis = 0; // 10 милли секунд
if ((*PORT_set & (1<<Pin_Set)) == 0) {
_delay_ms (50);
do { } while ((*PORT_set & (1<<Pin_Set)) == 0); // проверить отжата ли кнопка
_delay_ms(30);
if (last_millis > 25) {
return 1;
}
if (last_millis > 200) {
return 2;
}
return 100;
}
return 0;
};
int main(void)
{
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
TCCR0 |= (1<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0xB2;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK |= (1<<TOIE0);
KN_DDR |= (0<<KN);
KN_PORT |= (1<<KN);
sei();
for(;;){
i = skan_klav (KN, &KN_PIN);
_delay_ms(500);
i = 0;
}
};
Интересует вот этот кусок кода:
Спойлер
- Код:
char skan_klav (char Pin_Set, volatile char *PORT_set) {
last_millis = 0; // 10 милли секунд
if ((*PORT_set & (1<<Pin_Set)) == 0) {
_delay_ms (50);
do { } while ((*PORT_set & (1<<Pin_Set)) == 0); // проверить отжата ли кнопка
_delay_ms(30);
if (last_millis > 25) {
return 1;
}
if (last_millis > 200) {
return 2;
}
return 100;
}
return 0;
};
Этот кусок кода не выполняется по заложенному в него алгоритму.
Тем более дизассемблер показывает следующее
Спойлер
По чему часть кода не обрабатывается?
В архиве проект, протеус, и есе файлы.
- Вложения
-
- Primer.rar
- (23.57 KiB) Скачиваний: 223
Вс дек 25, 2016 16:22:22
Не сильно вникая в суть проблемы, спрошу: почему глобальная переменная, last_millis, которая изменяется в прерывании, не объявлена как volatile?
Powered by phpBB © phpBB Group.
phpBB Mobile / SEO by Artodia.