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

 
 
> Директива #define, Научить считать препроцессор
andrvisht
сообщение Nov 21 2005, 08:30
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Захотелось чтобы препроцессор вычислял значение которое нужно запихнуть в UBRR...
решил сделать вот так:
Код
#define _BAUND 9600
#define Fosc 4000000
#define BAUND (Fosc/(_BAUND*16))-1

В результате получил 176 а не 25

тогда попробовал вот так:

Код
#define _BAUND 9600
#define BAUND ((Fosc/_BAUND)/16)-1

и получил желанные 25


Но ведь записи то одинаковые, а результаты разные... ???

дальше хочу определить ошибку вот таким вариантом
Код
#define _UBRR ((Fosc/(BAUND+1))/16)
#define BAUND_ERROR ((_UBRR - _BAUND)/_BAUND)*1000

результат который хотелось видеть 1 (т.е. 0.1%) а получил 0 sad.gif

И хотелось бы выводить само значение ошибки, нашел директиву

Код
#warning любое текстовое сообщение


но оно не позволяет выводить результат расчета
типа
Код
#warning ошибка установки скорости обмена составляет BAUND_ERROR


Вообщем вопрос - как обрабатывается препроцессор и можно ли выводить на экран результат в численном виде ?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
andrvisht
сообщение Nov 24 2005, 07:25
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Код
#define _BAUD 38400
#define _U2X 2 // Doble Speed 1 or 2
#define _UBRR (( ClkFreq-(_BAUD*8L/_U2X) )/(_BAUD*16L/_U2X))
#define __BAUD (ClkFreq/((_UBRR*16L/_U2X)+16L/_U2X))
#define _BAUD_ERROR (((__BAUD*100000L)-(_BAUD*100000L))/_BAUD)

#if (_BAUD_ERROR >= 1000L)||(_BAUD_ERROR <= -1000L) // тысячные доли процента
#warning ошибка установки составляет _BAUD_ERROR
#endif

И все вроде хорошо только вот _BAUD_ERROR по умолчанию int и компилятор сообщает

Warning[Pe061]: integer operation result is out of range

если сделать попытку приведения типа
Код
#if ((long)_BAUD_ERROR >= 1000L)||((long)_BAUD_ERROR <= -1000L) // тысячные доли процента
#warning ошибка установки составляет _BAUD_ERROR
#endif


то вообще ругается
Error[Pe059]: function call is not allowed in a constant expression

Как быть ?
Go to the top of the page
 
+Quote Post
starter48
сообщение Nov 24 2005, 09:32
Сообщение #3


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

Группа: Свой
Сообщений: 112
Регистрация: 15-10-05
Из: Томск
Пользователь №: 9 680



Цитата(&-rey @ Nov 24 2005, 13:25) *
И все вроде хорошо только вот _BAUD_ERROR по умолчанию int и компилятор сообщает

Warning[Pe061]: integer operation result is out of range

Как быть ?

Я проверил эту конструкцию на Borland C. Нормально работает.
Похоже, препроцессор IAR сравнивать умеет только целые числа. (long) не поможет.
Считай в сотых долях процента, чтобы в диапазон целых чисел входило:
Код
#define _BAUD (38400L)
#define _U2X (2) // Doble Speed 1 or 2
#define ClkFreq (4000000L)
#define _UBRR (( ClkFreq-(_BAUD*8L/_U2X) )/(_BAUD*16L/_U2X))
#define __BAUD (ClkFreq/( (_UBRR+1L) *16L/_U2X) )
#define _BAUD_ERROR (((__BAUD-_BAUD)*10000L))/_BAUD)

#if (_BAUD_ERROR >= 100L)||(_BAUD_ERROR <= -100L) // сотые доли процента
#error погрешность установки скорости посл. порта более 1%
#endif


У меня тут предложение возникло...
А почему бы тебе не поставить кварц на 11.059MHz? Тогда стандартные скорости получишь без погрешности.
Только не говори, что 4000000 - частота внутр. RC генератора wink.gif
У меня нестабильно работало, когда я пытался от RC тактировать контроллер с посл. портом, т.к. термостабильность низкая у RC. Т.е. при прогреве контроллера или изменении напряжения питания частота RC уходила.

Сообщение отредактировал starter48 - Nov 24 2005, 09:43
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Nov 24 2005, 10:13
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(starter48 @ Nov 24 2005, 13:32) *
У меня тут предложение возникло...
А почему бы тебе не поставить кварц на 11.059MHz? Тогда стандартные скорости получишь без погрешности.

Конечно, я тоже не экономлю на кварцах smile.gif) Просто на C недавно перешел и перевожу свои библиотеки под IAR. Поэтому раз уж С то решил сделать типа универсального.
По поводу сравнений идея понятна, а что это IAR по поводу функции говорит ? Что у него на уме ?

И вот еще такой вопрос:
Захотел попробовать в качестве битов использовать битовое поле:
Код
typedef struct {// Структура битового поля
unsigned char bit0:1;
unsigned char bit1:1;
unsigned char bit2:1;
unsigned char bit3:1;
unsigned char bit4:1;
unsigned char bit5:1;
unsigned char bit6:1;
unsigned char bit7:1;
}bitfield;
static bitfield UARTstat={0,0,0,0,0,0,0,0};

и вот вопрос:

Возможно ли обратиться к структуре чтобы разом установить несколько битов ?
Просто ведь у IAR обращение например к порту можно сделать:
Код
PORTB_Bit0 = 1;
или
PORTB = 1<<PB0;


Или при таких желаниях мне лучьше подойдут Битовые маски ?
Go to the top of the page
 
+Quote Post
starter48
сообщение Nov 24 2005, 10:36
Сообщение #5


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

Группа: Свой
Сообщений: 112
Регистрация: 15-10-05
Из: Томск
Пользователь №: 9 680



Цитата(&-rey @ Nov 24 2005, 16:13) *
По поводу сравнений идея понятна, а что это IAR по поводу функции говорит ? Что у него на уме ?

То же самое. Вообще, работать должно smile.gif
Видать препроцессор у IAR не поддерживает явное указание типа.
Может у него опции есть какие-нибудь для включения совместимости.
Я не знаю. Почитай документацию в каталоге avr\doc.
Цитата(&-rey @ Nov 24 2005, 16:13) *
И вот еще такой вопрос:
Захотел попробовать в качестве битов использовать битовое поле:
и вот вопрос:
Возможно ли обратиться к структуре чтобы разом установить несколько битов ?
Просто ведь у IAR обращение например к порту можно сделать:
Код
PORTB_Bit0 = 1;
или
PORTB = 1<<PB0;


Или при таких желаниях мне лучьше подойдут Битовые маски ?

Посмотри как PORT в .h задаётся.
там даже специально дан пример:
Код
union {
  unsigned char AVR;
  struct {
    unsigned char AVR_Bit0:1,
    AVR_Bit1:1,
    AVR_Bit2:1,
    AVR_Bit3:1,
    AVR_Bit4:1,
    AVR_Bit5:1,
    AVR_Bit6:1,
    AVR_Bit7:1;
  };
};

Здесь к переменной AVR можно обращаться как к char: AVR=111,
а можно через биты: AVR_Bit5=1
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Nov 24 2005, 11:23
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(starter48 @ Nov 24 2005, 14:36) *
Посмотри как PORT в .h задаётся.
там даже специально дан пример:
Код
union {
  unsigned char AVR;
  struct {
    unsigned char AVR_Bit0:1,
    AVR_Bit1:1,
    AVR_Bit2:1,
    AVR_Bit3:1,
    AVR_Bit4:1,
    AVR_Bit5:1,
    AVR_Bit6:1,
    AVR_Bit7:1;
  };
};

Здесь к переменной AVR можно обращаться как к char: AVR=111,
а можно через биты: AVR_Bit5=1


Понял, а если я вот так захочу
AVR = (1<<AVR_Bit7)|(1<<AVR_Bit2)
то компилятор ме ругается, но у него AVR_Bitx все нули,
значит мне нужно их тоже определить в желаемом порядке ...
Исходя из описания портов вроде как да, но как на самом деле?
Go to the top of the page
 
+Quote Post
starter48
сообщение Nov 24 2005, 11:56
Сообщение #7


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

Группа: Свой
Сообщений: 112
Регистрация: 15-10-05
Из: Томск
Пользователь №: 9 680



Цитата(&-rey @ Nov 24 2005, 17:23) *
Понял, а если я вот так захочу
AVR = (1<<AVR_Bit7)|(1<<AVR_Bit2)
то компилятор ме ругается, но у него AVR_Bitx все нули,
значит мне нужно их тоже определить в желаемом порядке ...
Исходя из описания портов вроде как да, но как на самом деле?

А что ты этим выражением хотел сделать? blink.gif
Если установить биты7 и 2, то надо писать AVR |= (1<<7)|(1<<2),
или AVR_Bit7=AVR_Bit2=1.

Можешь ещё сделать по варианту, предложенному Rash:
Код
#include<avr_macros.h> //здесь макросы SETBIT, CLEARBIT...

void main(void)
{
  SETBIT(AVR, 7);SETBIT(AVR, 2);
}
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Nov 24 2005, 12:09
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



AVR_Bit7=AVR_Bit2=1
пробовал, но оно разделяет код на 2 команды, только если оптимизацию врубить тогда оно их сложит.
вообщем я понял, биты тоже нужно переопределить как хочеться.
Одной записью не обойтись sad.gif
Go to the top of the page
 
+Quote Post
starter48
сообщение Nov 24 2005, 12:21
Сообщение #9


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

Группа: Свой
Сообщений: 112
Регистрация: 15-10-05
Из: Томск
Пользователь №: 9 680



Цитата(&-rey @ Nov 24 2005, 18:09) *
AVR_Bit7=AVR_Bit2=1
пробовал, но оно разделяет код на 2 команды, только если оптимизацию врубить тогда оно их сложит.

Да, так и должно быть.
Цитата(&-rey @ Nov 24 2005, 18:09) *
вообщем я понял, биты тоже нужно переопределить как хочеться.
Одной записью не обойтись sad.gif

Если хочешь одной записью и с выключенной оптимизацией, то только явная запись поможет AVR |= (1<<7)|(1<<2). Что-то ты себе лишние проблемы создаешь smile.gif. Может книжек по С дать почитать?
Обычно бывает обратная проблема, когда пишешь
SETBIT(AVR,7);
SETBIT(AVR,2);
а оно их в одну команду ORI сливает. Тогда надо AVR объявить как volatile, чтобы выключить излишнюю оптимизацию этой переменной.
Go to the top of the page
 
+Quote Post
andrvisht
сообщение Nov 24 2005, 12:37
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(starter48 @ Nov 24 2005, 16:21) *
Если хочешь одной записью и с выключенной оптимизацией, то только явная запись поможет AVR |= (1<<7)|(1<<2). Что-то ты себе лишние проблемы создаешь smile.gif.

Это я понял, я имелл ввиду символьные имена битов. Их придеться еще раз определять
так же как PORTB_Bit0 и PB0
Цитата
Может книжек по С дать почитать?

Да вроде есть пока, только плохо без примеров применительно к AVR c точки зрения компактности.
Цитата
Обычно бывает обратная проблема, когда пишешь
SETBIT(AVR,7);
SETBIT(AVR,2);
а оно их в одну команду ORI сливает. Тогда надо AVR объявить как volatile, чтобы выключить излишнюю оптимизацию этой переменной.

Да, это я пробовал..
Вообщем я все понял, sanks.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- &-rey   Директива #define   Nov 21 2005, 08:30
- - vet   Препроцессор не умеет считать, его функция - разве...   Nov 21 2005, 08:41
- - starter48   Цитата(&-rey @ Nov 21 2005, 14:3...   Nov 21 2005, 08:53
- - &-rey   Спасибо, помогло. #define _BAUND 9600 #define Fosc...   Nov 21 2005, 09:37
|- - starter48   Цитата(&-rey @ Nov 21 2005, 15:3...   Nov 21 2005, 11:03
- - KRS   Вообще грамотнее использовать округление! #def...   Nov 21 2005, 09:52
|- - starter48   Цитата(KRS @ Nov 21 2005, 15:52) Вообще г...   Nov 21 2005, 11:23
|- - KRS   Цитата(starter48 @ Nov 21 2005, 14:23) Ци...   Nov 21 2005, 11:57
|- - starter48   Цитата(KRS @ Nov 21 2005, 17:57) нет имен...   Nov 21 2005, 12:34
- - &-rey   Ясно. Спасибо всем откликнувшимся... ))   Nov 21 2005, 10:01
- - Rash   ЦитатаВозможно ли обратиться к структуре чтобы раз...   Nov 24 2005, 10:21


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

 


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


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