реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Вопросы новичка, Первая программа, первые вопросы
Anjey_N
сообщение Jan 21 2007, 21:43
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Добрый вечер уважаемые знатоки! help.gif Написал первую программу в IAR 4.20/
У меня 2 вопроса:
1. Как разрешить глобальные прерывания?
2.Не работает команда PORTD=decode[Tens], хоть компилятор ошибок не выдаёт. Проверку производил в AVRStudio.
Программу прилагаю.

/*Программа выводит на индикатор числа с возрастанием
с 0 до 99 или с убыванием с 99 до 0 с частотой 1 сек
Если кнопка на выводе 0 порта С отжата - происходит счёт на увеличение,
если нажата - на уменьшение.
Среда IAR 4.20
Микроконтроллер AtMega 16
Кварц 16 МГц*/

#include <ioavr.h>

// Описание глобальных переменных
unsigned char n,c,flag,Ones,Tens;
char decode[10]={0xC0,0xFC,0xA4,0xB0,0x99,0x92,0x02,0xF8,0x80,0x90};
#define Bit(n) (1<<(n))

// Обработка прерываний по таймеру ТС0
#pragma vector=TIMER0_OVF_vect
__interrupt void FIRST (void)
{
PORTB=0x03; // выключаем индикатор
if (n){
PORTD=decode[Ones];
PORTB&=~Bit(0); // включаем 1 индикатор
}
else{
PORTD=decode[Tens];
PORTB&=~Bit(1); // включаем 2 индикатор
}
n=!n;
}

// Обработка прерываний по таймеру ТС1
#pragma vector=TIMER1_OVF_vect
__interrupt void SECOND (void)
{
TCNT1=0xC35A;
flag=1;
if ((PINC & Bit(0))!=0) c++; // увеличиваем, если кнопка отжата
else c--; // уменьшаем, если кнопка нажата
if (c==0x64) c=0x00;
if (c==0xFF) c=0x63;
}

// Преобразование 2-10 кода в 2-й
char CharToBCD(char c)
{
char high;
high=0;
while (c>=10){

high++;
c-=10;
}
return (high<<4)|c;
}

// Настройка регистров контроллера
void unit_avr (void)
{
//Порт А
PORTA=0x00;
DDRA=0xFF;
//Порт B
PORTB=0x03;
DDRB=0x03;
//Порт C
PORTC=0x01;
DDRC=0x00;
//Порт DD
PORTD=0xFF;
DDRD=0xFF;

// Настройка таймера ТС0
// Источник синхронизации: внутренний
// Частота на входе: 62,500 kHz
// Переполнение каждые 4 мс
TCCR0=0x03;
TCNT0=0x00;
OCR0=0x00;

// Настройка таймера ТС1
// Источник синхронизации: внутренний
// Частота на входе: 15,625 kHz
// Переполнение каждую секунду
TCCR1A=0x00;
TCCR1B=0x04;
TCNT1=0xC35A;
ICR1=0x00;
OCR1A=0x00;
OCR1B=0x00;

// Таймер 2 отключён
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// Внешние прерывания отключены
MCUCR=0x00;
MCUCSR=0x00;

// Разрешены прерывания по переполнению таймеров ТС0 и ТС1
TIMSK=0x05;

// Аналоговый компаратор отключён
ACSR=0x80;
SFIOR=0x00;
}

void main (void)
{
unit_avr();
// Разрешены глобальные прерывания
// __enable interrupt(); // здесь выдаёт ошибку
SREG|=Bit(7);

while (1){
while(flag){
// Place your code here
flag=0;
Tens=CharToBCD©;
PORTA=Tens;
Ones=Tens;
Ones=Ones&(0x0F);
Tens=Tens>>4;
}
}
}



Помогите разобраться!

Сообщение отредактировал Anjey_N - Jan 21 2007, 21:47
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 21 2007, 21:53
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Anjey_N @ Jan 22 2007, 01:43) *
Помогите разобраться!


чтобы использовать __enable_interrupt надо подключить intrinsics.h.

А вообще я разрешаю глобальные прерывания с помощью

Код
#define SEI() asm("sei")


команда PORTD=decode[Tens], не работает, возможно, из-за того что прерывания не разрешены


--------------------
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Jan 21 2007, 22:07
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Эта строчка "чтобы использовать __enable_interrupt надо подключить intrinsics.h." не сработала.
Помогло #define SEI() asm("sei")

Спасибо
А вот PORTD=decode[Tens] так и не работает

Сообщение отредактировал Anjey_N - Jan 21 2007, 22:08
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 21 2007, 22:15
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Anjey_N @ Jan 22 2007, 02:07) *
Эта строчка "чтобы использовать __enable_interrupt надо подключить intrinsics.h." не сработала.
Помогло #define SEI() asm("sei")

Спасибо
А вот PORTD=decode[Tens] так и не работает
Прерывания то хоть заработали?


--------------------
Go to the top of the page
 
+Quote Post
junoSynthesizer
сообщение Jan 22 2007, 00:47
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 83
Регистрация: 25-11-05
Из: odessa
Пользователь №: 11 397



Цитата(Anjey_N @ Jan 21 2007, 21:07) *
А вот PORTD=decode[Tens] так и не работает


в чём выражается "не работает" ?


--------------------
Вся жизнь - ништяк, все бабы - леди, а солнце - шар дающий свет
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jan 22 2007, 02:18
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



__enable_interrupt(); // Разрешить прерывания
Go to the top of the page
 
+Quote Post
satellite-plus
сообщение Jan 22 2007, 10:45
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 51
Регистрация: 8-01-07
Из: Одесса
Пользователь №: 24 196



Цитата(Anjey_N @ Jan 21 2007, 20:43) *
Помогите разобраться!


#pragma language=extended
#include <iom16.h>
#include <ina90.h>
#include <string.h>


__flash char decode[10]={0xC0,0xFC,0xA4,0xB0,0x99,0x92,0x02,0xF8,0x80,0x90};


_SEI(); // разрешение прерываний
_CLI(); // запрет прерываний


--------------------
Опыт - это та чудесная штука, которая позволяет вам узнать ошибку, когда вы ее повторите.
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Jan 22 2007, 11:31
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



junoSynthesizer Дата Сегодня, 01:47

(Anjey_N @ Jan 21 2007, 21:07)

А вот PORTD=decode[Tens] так и не работает



в чём выражается "не работает" ?


В PORTD должно выводится значение из массива decode[11] с порядковым номером, вычисленном для переменной Tens. Это не работает.



Прерывания работают как по команде __enable_interrupt(); при #include <intrinsics.h>, так и при _SEI();


Может посмотрите ещё раз код, может я где-то ошибаюсь?


#include <ioavr.h>
#include <intrinsics.h> // для команды __enable_interrupt
#pragma language=extended
#include <iom16.h>
#include <ina90.h>
#include <string.h>
// Описание глобальных переменных
unsigned char n,c,flag,Ones,Tens;
//char decode[10]={0xC0,0xFC,0xA4,0xB0,0x99,0x92,0x02,0xF8,0x80,0x90};
__flash char decode[10]={0xC0,0xFC,0xA4,0xB0,0x99,0x92,0x02,0xF8,0x80,0x90};
#define Bit(n) (1<<(n))
#define Key (PINC & Bit(0))

// Обработка прерываний по таймеру ТС0
#pragma vector=TIMER0_OVF_vect
__interrupt void FIRST (void)
{
PORTB=0x03; // выключаем индикатор
if (n){
PORTD=decode[Ones]; // не работает
PORTB&=~Bit(0); // включаем 1 индикатор
}
else{
PORTD=decode[Tens]; // не работает
PORTB&=~Bit(1); // включаем 2 индикатор
}
n=!n;
}

// Обработка прерываний по таймеру ТС1
#pragma vector=TIMER1_OVF_vect
__interrupt void SECOND (void)
{
TCNT1=0xC35A;
flag=1;
if (Key) c++; // увеличиваем, если кнопка отжата
else c--; // уменьшаем, если кнопка нажата
if (c==0x64) c=0x00;
if (c==0xFF) c=0x63;
}

// Преобразование 2-10 кода в 2-й
char CharToBCD(char c)
{
char high;
high=0;
while (c>=10){

high++;
c-=10;
}
return (high<<4)|c;
}

// Настройка регистров контроллера
void unit_avr (void)
{
//Порт А
PORTA=0x00;
DDRA=0xFF;
//Порт B
PORTB=0x03;
DDRB=0x03;
//Порт C
PORTC=0x01;
DDRC=0x00;
//Порт DD
PORTD=0xFF;
DDRD=0xFF;

// Настройка таймера ТС0
// Источник синхронизации: внутренний
// Частота на входе: 62,500 kHz
// Переполнение каждые 4 мс
TCCR0=0x03;
TCNT0=0x00;
OCR0=0x00;

// Настройка таймера ТС1
// Источник синхронизации: внутренний
// Частота на входе: 15,625 kHz
// Переполнение каждую секунду
TCCR1A=0x00;
TCCR1B=0x04;
TCNT1=0xC35A;
ICR1=0x00;
OCR1A=0x00;
OCR1B=0x00;

// Таймер 2 отключён
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// Внешние прерывания отключены
MCUCR=0x00;
MCUCSR=0x00;

// Разрешены прерывания по переполнению таймеров ТС0 и ТС1
TIMSK=0x05;

// Аналоговый компаратор отключён
ACSR=0x80;
SFIOR=0x00;
}

void main (void)
{
unit_avr();
// Разрешены глобальные прерывания
__enable_interrupt();
while (1){
while(flag){
// Place your code here
flag=0;
Tens=CharToBCD©;
PORTA=Tens;
Ones=Tens;
Ones=Ones&(0x0F);
Tens=Tens>>4;
}
}
}
Go to the top of the page
 
+Quote Post
prottoss
сообщение Jan 22 2007, 11:38
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Anjey_N @ Jan 22 2007, 15:31) *
...

PORTD=decode[Tens]; // не работает
PORTB&=~Bit(1); // включаем 2 индикатор

...
А что, строчка ниже подчеркнутой работает?


--------------------
Go to the top of the page
 
+Quote Post
otrog
сообщение Jan 22 2007, 11:54
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 232
Регистрация: 22-02-06
Из: Воронеж
Пользователь №: 14 589



Цитата(Anjey_N @ Jan 22 2007, 11:31) *
#include <ioavr.h>
#include <intrinsics.h> // для команды __enable_interrupt
#pragma language=extended
#include <iom16.h>
#include <ina90.h>
#include <string.h>
// Описание глобальных переменных
unsigned char n,c,flag,Ones,Tens;
//char decode[10]={0xC0,0xFC,0xA4,0xB0,0x99,0x92,0x02,0xF8,0x80,0x90};
__flash char decode[10]={0xC0,0xFC,0xA4,0xB0,0x99,0x92,0x02,0xF8,0x80,0x90};
#define Bit(n) (1<<(n))
#define Key (PINC & Bit(0))

// Обработка прерываний по таймеру ТС0
#pragma vector=TIMER0_OVF_vect
__interrupt void FIRST (void)
{
PORTB=0x03; // выключаем индикатор
if (n){
PORTD=decode[Ones]; // не работает
PORTB&=~Bit(0); // включаем 1 индикатор
}
else{
PORTD=decode[Tens]; // не работает
PORTB&=~Bit(1); // включаем 2 индикатор
}
n=!n;
}

Похоже что компилятор заоптимизировал переменную n.
Попробуйте объявить ее так:
Код
volatile unsigned char n;


--------------------
Истина рождается в спорах; но когда страсти кипят, истина испаряется.
Go to the top of the page
 
+Quote Post
satellite-plus
сообщение Jan 22 2007, 12:11
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 51
Регистрация: 8-01-07
Из: Одесса
Пользователь №: 24 196



Посмотри как это делается.

Сообщение отредактировал satellite-plus - Jan 22 2007, 12:15
Прикрепленные файлы
Прикрепленный файл  volt.zip ( 2.43 килобайт ) Кол-во скачиваний: 68
 


--------------------
Опыт - это та чудесная штука, которая позволяет вам узнать ошибку, когда вы ее повторите.
Go to the top of the page
 
+Quote Post
GDI
сообщение Jan 22 2007, 12:13
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Цитата
n=!n;


здесь инверсию хотите сделать? Имхо надо n = ~n;


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 22 2007, 12:48
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(GDI @ Jan 22 2007, 11:13) *
Цитата
n=!n;

здесь инверсию хотите сделать? Имхо надо n = ~n;
Как раз в этом случае правильнее !n, ибо переменная по логике программы должна принимать два значения - "ноль" и "не ноль". И конструкция !n это обеспечивает. А вот если n в программе каким-то образом примет любое значение, отличное от 0 или 0xFF, то конструкция ~n всегда будет давать в результате "не ноль":
Код
if(n) {

} else {

}
Для Anjey_N:
Код
Tens=CharToBCD©;   // A
PORTA=Tens;
Ones=Tens;                // B
Ones=Ones&(0x0F);
Tens=Tens>>4;          // C
                                 // D
Некорректно написан кусок программы. Если прерывание FIRST возникнет в любом месте между A и D то Tens будет иметь значение выходящее за пределы массива decode. Также между B и C Ones имеет некорректное значение. Надо пользоваться временной переменной или запрещать прерывания:
Код
__disable_interrupt();
Tens=CharToBCD( с );
PORTA=Tens;
Ones=Tens;
Ones=Ones&(0x0F);
Tens=Tens>>4;
__enable_interrupt();

или

unsigned char Tmp = CharToBCD( c );
PORTA=Tmp;
Ones=Tmp & 0x0F;
Tens=Tmp >> 4;

Кстати, чтобы компилятор не ругался на __enable_interrupt(), __disable_interrupt() и т.п. достаточно включить <inavr.h>, intrinsic.h подключится из него автоматически.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Anjey_N
сообщение Jan 22 2007, 12:51
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 80
Регистрация: 12-01-07
Из: Энергодар Украина
Пользователь №: 24 374



Цитата(prottoss @ Jan 22 2007, 12:38) *
Цитата(Anjey_N @ Jan 22 2007, 15:31) *


...

PORTD=decode[Tens]; // не работает
PORTB&=~Bit(1); // включаем 2 индикатор

...
А что, строчка ниже подчеркнутой работает?


Да, эта строчка работает
Go to the top of the page
 
+Quote Post
aesok
сообщение Jan 22 2007, 13:13
Сообщение #15


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Переменные 'flag', 'c' - должны быть volatile

Анатолий.
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 16:56
Рейтинг@Mail.ru


Страница сгенерированна за 0.0151 секунд с 7
ELECTRONIX ©2004-2016