|
Директива #define, Научить считать препроцессор |
|
|
|
Nov 21 2005, 08:30
|
Местный
  
Группа: Свой
Сообщений: 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  И хотелось бы выводить само значение ошибки, нашел директиву Код #warning любое текстовое сообщение но оно не позволяет выводить результат расчета типа Код #warning ошибка установки скорости обмена составляет BAUND_ERROR Вообщем вопрос - как обрабатывается препроцессор и можно ли выводить на экран результат в численном виде ?
|
|
|
|
|
 |
Ответов
|
Nov 24 2005, 07:25
|
Местный
  
Группа: Свой
Сообщений: 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 Как быть ?
|
|
|
|
|
Nov 24 2005, 09:32
|

Частый гость
 
Группа: Свой
Сообщений: 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 генератора  У меня нестабильно работало, когда я пытался от RC тактировать контроллер с посл. портом, т.к. термостабильность низкая у RC. Т.е. при прогреве контроллера или изменении напряжения питания частота RC уходила.
Сообщение отредактировал starter48 - Nov 24 2005, 09:43
|
|
|
|
|
Nov 24 2005, 10:13
|
Местный
  
Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064

|
Цитата(starter48 @ Nov 24 2005, 13:32)  У меня тут предложение возникло... А почему бы тебе не поставить кварц на 11.059MHz? Тогда стандартные скорости получишь без погрешности. Конечно, я тоже не экономлю на кварцах  ) Просто на 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; Или при таких желаниях мне лучьше подойдут Битовые маски ?
|
|
|
|
|
Nov 24 2005, 10:36
|

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

|
Цитата(&-rey @ Nov 24 2005, 16:13)  По поводу сравнений идея понятна, а что это IAR по поводу функции говорит ? Что у него на уме ? То же самое. Вообще, работать должно  Видать препроцессор у 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
|
|
|
|
|
Nov 24 2005, 11:23
|
Местный
  
Группа: Свой
Сообщений: 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 все нули, значит мне нужно их тоже определить в желаемом порядке ... Исходя из описания портов вроде как да, но как на самом деле?
|
|
|
|
|
Nov 24 2005, 11:56
|

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

|
Цитата(&-rey @ Nov 24 2005, 17:23)  Понял, а если я вот так захочу AVR = (1<<AVR_Bit7)|(1<<AVR_Bit2) то компилятор ме ругается, но у него AVR_Bitx все нули, значит мне нужно их тоже определить в желаемом порядке ... Исходя из описания портов вроде как да, но как на самом деле? А что ты этим выражением хотел сделать? Если установить биты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); }
|
|
|
|
|
Nov 24 2005, 12:09
|
Местный
  
Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064

|
AVR_Bit7=AVR_Bit2=1 пробовал, но оно разделяет код на 2 команды, только если оптимизацию врубить тогда оно их сложит. вообщем я понял, биты тоже нужно переопределить как хочеться. Одной записью не обойтись
|
|
|
|
|
Nov 24 2005, 12:21
|

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

|
Цитата(&-rey @ Nov 24 2005, 18:09)  AVR_Bit7=AVR_Bit2=1 пробовал, но оно разделяет код на 2 команды, только если оптимизацию врубить тогда оно их сложит. Да, так и должно быть. Цитата(&-rey @ Nov 24 2005, 18:09)  вообщем я понял, биты тоже нужно переопределить как хочеться. Одной записью не обойтись  Если хочешь одной записью и с выключенной оптимизацией, то только явная запись поможет AVR |= (1<<7)|(1<<2). Что-то ты себе лишние проблемы создаешь  . Может книжек по С дать почитать? Обычно бывает обратная проблема, когда пишешь SETBIT(AVR,7); SETBIT(AVR,2); а оно их в одну команду ORI сливает. Тогда надо AVR объявить как volatile, чтобы выключить излишнюю оптимизацию этой переменной.
|
|
|
|
|
Nov 24 2005, 12:37
|
Местный
  
Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064

|
Цитата(starter48 @ Nov 24 2005, 16:21)  Если хочешь одной записью и с выключенной оптимизацией, то только явная запись поможет AVR |= (1<<7)|(1<<2). Что-то ты себе лишние проблемы создаешь  . Это я понял, я имелл ввиду символьные имена битов. Их придеться еще раз определять так же как PORTB_Bit0 и PB0 Цитата Может книжек по С дать почитать? Да вроде есть пока, только плохо без примеров применительно к AVR c точки зрения компактности. Цитата Обычно бывает обратная проблема, когда пишешь SETBIT(AVR,7); SETBIT(AVR,2); а оно их в одну команду ORI сливает. Тогда надо AVR объявить как volatile, чтобы выключить излишнюю оптимизацию этой переменной. Да, это я пробовал.. Вообщем я все понял, sanks.
|
|
|
|
Сообщений в этой теме
&-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
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|