CodeVision AVR в вопросах и ответах
Re: CodeVision AVR в вопросах и ответах
Есть две переменные типа char A,B
и одна переменная int X
хочу записать A как верхний байт в X, а B как нижний.
Самый простой метод который мне приходит в голову это
1. X=A;
2. X=X<<8;
3. X=X|B;
можно объединить 1-й и 2-й шаг в 1, но не уверен что любая оптимизация правильно обработает
X=A<<8;
Если компилятор обработает только 8 бит, то в X попадут одни нули.
Но вопрос собственно не в этом, а как это сделать на Си, экономя на максимум ресурсы процессора и флэш памяти.
Ведь операция смещения на 8 бит в лево это целых 8 операций смещения по 1 разу.
А также необходима обратная операция из int взять данные также загрузив в А верхний байт, а в B нижний и опять самым оптимальным способом.
Может быть с помощью указателей?
и одна переменная int X
хочу записать A как верхний байт в X, а B как нижний.
Самый простой метод который мне приходит в голову это
1. X=A;
2. X=X<<8;
3. X=X|B;
можно объединить 1-й и 2-й шаг в 1, но не уверен что любая оптимизация правильно обработает
X=A<<8;
Если компилятор обработает только 8 бит, то в X попадут одни нули.
Но вопрос собственно не в этом, а как это сделать на Си, экономя на максимум ресурсы процессора и флэш памяти.
Ведь операция смещения на 8 бит в лево это целых 8 операций смещения по 1 разу.
А также необходима обратная операция из int взять данные также загрузив в А верхний байт, а в B нижний и опять самым оптимальным способом.
Может быть с помощью указателей?
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: CodeVision AVR в вопросах и ответах
Код: Выделить всё
X = (int)A << 8;
X |= B;Но на самом деле, что этот вариант, что Ваш - разницы никакой. Я практически уверен, что компилятор сведёт это к одному и тому же ассемблерному коду. Причём не будет ничего смещать, а просто положит байты в регистровую пару. Такие вещи, как сдвиги на 8 компилятор делает по-умному. Ему даже можно писать * 256 вместо <<8 - ему всё равно (если, конечно, оптимизация не отключена вообще).
А ещё для таких вещей (интерпретация области памяти по-разному) можно использовать объединение:
Код: Выделить всё
typedef union {
int X;
struct {
char B;
char A;
}
} myUnion;
myUnion m;
m.A = 0x34;
m.B = 0x87;
// Теперь m.X равно 0x3487Иногда бывает удобно, например, при считывании из шины (I2C, SPI, 1-wire) 8-битных величин, которые потом комбинируются автоматически в 16-битные за счёт объединений.
Re: CodeVision AVR в вопросах и ответах
Спасибо за идею.
Кстати codevision ругался (ilegal simbol) и непонятно чего хотел
А атмел студио сразу указала на то что отсутствует точка с запятой в тексте она красная.
typedef union {
int X;
struct {
char B;
char A;
};
} myUnion;
myUnion m;
m.A = 0x34;
m.B = 0x87;
Кстати codevision ругался (ilegal simbol) и непонятно чего хотел
А атмел студио сразу указала на то что отсутствует точка с запятой в тексте она красная.
typedef union {
int X;
struct {
char B;
char A;
};
} myUnion;
myUnion m;
m.A = 0x34;
m.B = 0x87;
Re: CodeVision AVR в вопросах и ответах
Мужики, подскажите.
Есть пир, отвечающий на команды с компа по RS485.
Уже долго бьюсь, но никак не могу понять почему у меня драйвер adm485 отключается раньше, чем заканчивается передача по UART.
Вот код такой:
case SendStat:
Rs485SendEN=1; //driver on
UCSRA |= (1<<TXC);//sbros flaga txc
printf("%u",Rel1Stat); //esli rele wklucheno otprawlyaem 1
while(!(UCSRA & (1<<TXC)));//zdem konza posilki
Rs485SendEN=0;
Почему то while(!(UCSRA & (1<<TXC))); не работает - где ошибка?
Еще есть вопрос по приему комманд, но это отдельно.
Есть пир, отвечающий на команды с компа по RS485.
Уже долго бьюсь, но никак не могу понять почему у меня драйвер adm485 отключается раньше, чем заканчивается передача по UART.
Вот код такой:
case SendStat:
Rs485SendEN=1; //driver on
UCSRA |= (1<<TXC);//sbros flaga txc
printf("%u",Rel1Stat); //esli rele wklucheno otprawlyaem 1
while(!(UCSRA & (1<<TXC)));//zdem konza posilki
Rs485SendEN=0;
Почему то while(!(UCSRA & (1<<TXC))); не работает - где ошибка?
Еще есть вопрос по приему комманд, но это отдельно.
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: CodeVision AVR в вопросах и ответах
Мужики, подскажите
В родной документации (Mega48) есть пример:
The following code examples show a simple USART transmit function based on polling of the Data Register Empty (UDREn) Flag.
Код: Выделить всё
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSRnA & (1<<UDREn)) );
/* Put data into buffer, sends the data */
UDRn = data;
}тоже из документации:
Bit 5 – UDREn: USART Data Register Empty
The UDREn Flag indicates if the transmit buffer (UDRn) is ready to receive new data. If UDREn is one, the buffer is empty, and therefore ready to be written.
Re: CodeVision AVR в вопросах и ответах
Так и
The TXC Flag can be used
to check that the Transmitter has completed all transfers, Note that the TXC Flag must be
cleared before each transmission (before UDR is written) if it is used for this purpose.
А The UDR Flag indicates if the transmit buffer (UDRn) is ready to receive new data, но как я понял в шифт регистре все равно есть данные еще, после высылки которых как раз флаг TXC устанавливается.
The TXC Flag can be used
to check that the Transmitter has completed all transfers, Note that the TXC Flag must be
cleared before each transmission (before UDR is written) if it is used for this purpose.
А The UDR Flag indicates if the transmit buffer (UDRn) is ready to receive new data, но как я понял в шифт регистре все равно есть данные еще, после высылки которых как раз флаг TXC устанавливается.
Re: CodeVision AVR в вопросах и ответах
вот :
A data transmission is initiated by loading the transmit buffer with the data to be transmitted. The
CPU can load the transmit buffer by writing to the UDR I/O location. The buffered data in the
transmit buffer will be moved to the Shift Register when the Shift Register is ready to send a new
frame
A data transmission is initiated by loading the transmit buffer with the data to be transmitted. The
CPU can load the transmit buffer by writing to the UDR I/O location. The buffered data in the
transmit buffer will be moved to the Shift Register when the Shift Register is ready to send a new
frame
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: CodeVision AVR в вопросах и ответах
Пример от производителя: Application Note AVR306: Using the AVR® UART in C
http://microsin.net/programming/AVR/uartrs232.html
Код: Выделить всё
/* Read and write functions */
unsigned char ReceiveByte( void )
{
while ( !(USR & (1<<RXC)) ); /* wait for incomming data */
/* return the data */
return UDR;
}
void TransmitByte( unsigned char data )
{
while ( !(USR & (1<<UDRE)) ); /* wait for empty transmit buffer */
UDR = data; /* start transmittion */
}Поскольку передача во времени происходит не мгновенно (биты выходят из передатчика последовательно, друг за другом), то бездумно пихать данные в регистр UDR нельзя - нужно дождаться окончания передачи предыдущего байта. О том, что UDR пуст и готов к приему нового байта, сигнализирует бит UDRE, он же вызовет аппаратное прерывание по опустошению буфера.
http://microsin.net/programming/AVR/uartrs232.html
Re: CodeVision AVR в вопросах и ответах
Так об этом я и не спорю.
Но всё же это для того чтобы понять что можно именно начать передачу (пихать в буфер
, т.е. когда пердатчик готов.
Но UDR не говорит нам что ВСЕ биты фышли и стоп бит тоже. Мне же надо знать именно когда вышел стоп бит и можно выключить передатчик DE в ADMке.
Но всё же это для того чтобы понять что можно именно начать передачу (пихать в буфер
Но UDR не говорит нам что ВСЕ биты фышли и стоп бит тоже. Мне же надо знать именно когда вышел стоп бит и можно выключить передатчик DE в ADMке.
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: CodeVision AVR в вопросах и ответах
вы ж функцией printf не один байт отправляете. Вроде же TXC установится после первого переданного символа, если не успели записать новые данные. У вас есть сброс этого бита в функции putchar? Прерывания другие в вашей программе используются?
Re: CodeVision AVR в вопросах и ответах
Да. Обычно отправляю не один байт.
Прерывания только таймеры. Putchar в теле нет. Пользуюсь готовой библиотекой *.h
Вот так например:
if(CmndSymb[0]==Adres1){
Rs485SendEN=1;
UCSRA |= (1<<TXC);//sbros flaga txc
printf("Status from adres%u\nRel1=%i,Led2Value=%i(pr),TimeTmr=%u(min),", Adres1,Rel1Stat,Led2Value,TimeTmr/845);
// printf("Daytime=%u",Daytime);
while(!(UCSRA & (1<<TXC)));// //poka flag ne ustanowilsya --konez peredachi
Rs485SendEN=0;};
Прерывания только таймеры. Putchar в теле нет. Пользуюсь готовой библиотекой *.h
Вот так например:
if(CmndSymb[0]==Adres1){
Rs485SendEN=1;
UCSRA |= (1<<TXC);//sbros flaga txc
printf("Status from adres%u\nRel1=%i,Led2Value=%i(pr),TimeTmr=%u(min),", Adres1,Rel1Stat,Led2Value,TimeTmr/845);
// printf("Daytime=%u",Daytime);
while(!(UCSRA & (1<<TXC)));// //poka flag ne ustanowilsya --konez peredachi
Rs485SendEN=0;};
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: CodeVision AVR в вопросах и ответах
Прерывания только таймеры
Посмотрите как в вашей готовой библиотеке putchar организован. В папке кожевижена есть пример 2usart_lcd - там есть готовый putchar. Если есть прерывания, представим в UDR вы записали данные, далее в putchar ожидаем бит UDRE, но тут произошло прерывание, помешавшее записать новые данные в UDR вовремя - TXC установится.
Re: CodeVision AVR в вопросах и ответах
Wasily писал(а):В папке кожевижена есть пример 2usart_lcd - там есть готовый putchar.
case USART0: // the output will be directed to USART0
while ((UCSR0A & 1<<UDRE)==0);
UDR0=c;
по сути функция ждет освобождения буффера.
Wasily писал(а):Посмотрите как в вашей готовой библиотеке putchar организован.
Как? мало знаний у меня.
Как тогда правильнее решить мою проблему?
Кстати пробывал писать cli и sei - не помогло. Получается таймер не причем...
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18544
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: CodeVision AVR в вопросах и ответах
по-моему, вам надо ждать, когда оба бита будут установлены UDRE и TXC - это будет означать, что все данные переданы и буфер пуст. после этого можно и выключать драйвер.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: CodeVision AVR в вопросах и ответах
ARV писал(а):по-моему, вам надо ждать, когда оба бита будут установлены UDRE и TXC - это будет означать, что все данные переданы и буфер пуст. после этого можно и выключать драйвер.
ок, попробую вскоре
- oleg110592
- Друг Кота
- Сообщения: 3832
- Зарегистрирован: Сб сен 10, 2011 17:46:25
Re: CodeVision AVR в вопросах и ответах
совсем тупой способ - после printf сделать задержку, перед переключением 485, сторона принимающая тоже не должна сразу по приему строки отправлять сразу назад свою передачу. Видел подобное в чужом коде - после записи в UDR, ожидание UDRE, и небольшая программная задержка. Да и сам такое давненько применил - некрасиво, но работает. Наверное можно на прерываниях сделать.
Re: CodeVision AVR в вопросах и ответах
Пробовал, конечно работает. Но как то не профессионально
.
Подбирать под разную скорость надо задержку.
Подбирать под разную скорость надо задержку.
Re: CodeVision AVR в вопросах и ответах
Недавно сталкивался точно с такой проблемой. Проблема оказалась в том что без использовании прерываний(по TXC) бит TXC не сбрасывается.
т.е после каждой передачи его надо в ручную сбрасывать.
т.е после каждой передачи его надо в ручную сбрасывать.
- sphincs
- Нашел транзистор. Понюхал.
- Сообщения: 174
- Зарегистрирован: Вт сен 11, 2012 09:13:52
- Откуда: Брест, Беларусь
- Контактная информация:
Re: CodeVision AVR в вопросах и ответах
где можно взять библиотеку для работы с LCD на HD44780 через I2C расширитель PCF8574 для CV AVR? желательно с пояснениями по ней
Re: CodeVision AVR в вопросах и ответах
Всем доброго времени суток. У меня тут возник вот такой вопрос. Допустим я ниписал некуюю программу А и программу Б. Программы одинакового характера, но с разными условиями. Пусть это будет даже программы для имерения чего нибудь при помощи АЦП с отображением результатов на ЖКИ. Как сделать так, чтобы после нажатия на кнопку на ЖКИ отображались результаты программы Б а при повторном нажатии опять программа А ну и так далее. Одиночные программы работают. Я думаю лучше использовать внешнее прерывания или всё-таки опрос кнопок? Ещё я думаю что нужно после нажатия на кнопку переходить к соответсвующему программному коду? Я ещё только делаю первые шаги с МК. Буду очень благодарен за помощь.