Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Работа с отдельными битами под AVR Studio под С
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Master_MW
Доброго времени суток , коллеги. Проблема в следующем. Пересмотрев достаточное количество материалов по программированию AVR на С, я так и не нашел ответа на сл. вопрос: как прочитать/изменить отдельный бит информации регистра? Для установления одного бита в лог. 1 есть библиотечная директива _BV(и та не везде работает). А как быть с чтением отдельных бит и установкой в ноль? На ассемблере ни для AVR, ни для PIC таких проблем не возникает.
MrYuran
byte |= (1<<bit) // - установка бита bit
byte &= ~(1<<bit) // - сброс бита bit

Есть куча различных макросов на эту тему

1<<bit можно заменить любой маской
_Pasha
Тоже в свое время "многа думаль". Додумался вот до чего:

1. Структуры и объединения с битовыми полями  smile.gif это не я додумался, конечно

Код
typedef struct
{
unsigned flag1:1;
unsigned flag2:1;
} flagset_t;
union Tflags
{
flagset_t bits;
uint8_t byte;
} flags;

// получается
flags.byte =0;
flags.bits.flag1 = 0;

Обратите внимание, что биты выделяются от младшего к старшему
2. Это все конечно хорошо, но до тех пор, пока у нас нет обращения к периферии. Поскольку работа с битовыми полями в описании потрохов МК не прижилась, нет смысла упорствовать, сочинять типы для "красоты текста" и для портов лучше применять _BV и иже с ними. Лично меня не плющит написАть (1<<bit_name)
ЗЫ (bit_mask << bit_mask_offset) тоже частенько встречаются.
Сергей Борщ
Цитата(Master_MW @ Mar 5 2009, 13:24) *
Для установления одного бита в лог. 1 есть библиотечная директива _BV(и та не везде работает).
Приведите пример не работы.
_Pasha
Кстати, _BV() породили, а  _nBV(val) в смысле ~(1<<val) не захотели sad.gif Зажали понятие.
VladimirYU
Цитата(Master_MW @ Mar 5 2009, 14:24) *
Доброго времени суток , коллеги. Проблема в следующем. Пересмотрев достаточное количество материалов по программированию AVR на С, я так и не нашел ответа на сл. вопрос: как прочитать/изменить отдельный бит информации регистра? Для установления одного бита в лог. 1 есть библиотечная директива _BV(и та не везде работает). А как быть с чтением отдельных бит и установкой в ноль? На ассемблере ни для AVR, ни для PIC таких проблем не возникает.

Посмотрите на сахаре, эта тема вроде до сих пор обсуждается.
[url="http://caxapa.ru"]
mdmitry
Эта тема активно обсуждалась на форуме AVR в прошлом году. Спрашивающему поиск в помощь.
Присоединяюсь к реплике Сергея Борща. Может не был #define _BV определен или файл (avr/sfr_defs.h) подключен? Это не библиотечная функция.
Master_MW
Сергей Борщ, Так, например, не хочет работать

PORTB=_BV(PORTB1);

mdmitry, Сергей Борщ,
Насчёт _BV mdmitry оказался прав, хотя в книге Ю.А. Шпака указано что _BV() библиотечный макрос (Ю.А. Шпак. Программирование на языке С для AVR и PIC микроконтроллеров, стр. 165). Проблема решилась с подключением файла avr/sfr_defs.h В тамошнем примере код до функции отработки прерывания следующий:
CODE
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#if defined(__AVR_AT90S2313__)
# define OC1 PB3
# define OCR OCR1
# define DDROC DDRB
#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
# define OC1 PB1
# define DDROC DDRB
# define OCR OCR1
#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || \
defined(__AVR_AT90S4434__) || defined(__AVR_AT90S8535__) || \
defined(__AVR_ATmega163__)
# define OC1 PD5
# define DDROC DDRD
# define OCR OCR1A
#endif

#if defined(COM11)
# define XCOM11 COM11
#elif defined(COM1A1)
# define XCOM11 COM1A1
#endif

enum { UP, DOWN };

unsigned int pwm;
unsigned char direction;
;


К слову, вектор прерывания там тоже нерабочий , вместо

INTERRUPT(SIG_OWERFLOW1)

для корректной работы нужно использовать

ISR(TIMER0_OVF_vect){
OCR0++; if(OCR0==255) OCR0=0;}

Это простенький, реально заработавший в железе пример.
Тем не менее, ситуация достаточно прояснилась , - спасибо всем за помощь. Дело в том , что раньше я писал все свои проекты управления на VHDL, а теперь необходимы некоторые вычисл. мощности, которые проще сделать на МК, нежели на ПЛИС...
Сергей Борщ
Цитата(Master_MW @ Mar 5 2009, 22:08) *
Так, например, не хочет работать
PORTB=_BV(PORTB1);
Ммм... поясните пожалуйста термин "не хочет работать". Это выражение должно записать число 0x02 в PORTB. Затерев при этом предыдущее значение всех 8 битов.

Цитата(Master_MW @ Mar 5 2009, 22:08) *
в книге Ю.А. Шпака указано что _BV() библиотечный макрос
В этом со Шпаком можно согласиться. Это действительно макрос (он объявлен через #define), а не директива, как вы написали в первом сообщении, и он действительно часть библиотеки (avr-libc).
Цитата(Master_MW @ Mar 5 2009, 22:08) *
Проблема решилась с подключением файла avr/sfr_defs.h
Это несколько странно - этот файл включен в avr/io.h, поэтому должен подключаться автоматически при подключении avr/io.h. А без подключения avr/io.h компилятор не знает что такое PORTB и PORTB1. Становится совсем непонятно, как же у вас _BV() не работало.
Цитата(Master_MW @ Mar 5 2009, 22:08) *
для корректной работы нужно использовать

ISR(TIMER0_OVF_vect)
Помню из детства: "однако, за время пути собака могла подрасти". Время идет, компилятор развивается. Книга была написана давно, примеры в ней относятся к компилятору версии 2005-2006 года (если память не изменяет).
_Pasha
Цитата(Master_MW @ Mar 5 2009, 23:08) *
INTERRUPT(SIG_OWERFLOW1)
для корректной работы нужно использовать
ISR(TIMER0_OVF_vect){

Имена SIG_xxxxx не рекомендуются к дальнейшему применению. (см. понятие "Deprecated features")
Упс, опередили.
Master_MW
Цитата
Это несколько странно - этот файл включен в avr/io.h, поэтому должен подключаться автоматически при подключении avr/io.h. А без подключения avr/io.h компилятор не знает что такое PORTB и PORTB1. Становится совсем непонятно, как же у вас _BV() не работало.


Согласен... Хотя я, наверное, неправильно выразился, - компилятор не понимает, что такое PORTB1, например, либо имя бита, выставл. общее разрешение прерываний... Но ладно, полученной информации вполне достаточно, чтобы во всем оставшимся разобраться самому. Думаю, если у вас остались вопросы, то можно договориться , о том, что я могу выслать по электронной почте проект, - так будет проще ... Полагаю, так на свой вопрос вы ответите гораздо быстрее, если возникнет желание - пишите в личку.
Legotron
У меня есть вот такой вопрос:

Как вы(обращение ко всем) работает с некоторой периферией у которой регистры устанавливаются по различным протоколам (USART, SPI, I2C) и имеют признаки only R/ only W/ RW, default-состояния отличные от 0?
Я встречал подходы с использованием массива shadow-регистров, но мне не понравился тот пример по изящности исполнения.
Если не жалко покажите свои наработки smile.gif
SysRq
Цитата(Legotron @ Mar 25 2009, 17:34) *
У меня есть вот такой вопрос...

С флагом UDRE в регистре состояния USART, который в 1 при старте, ничего никогда не делал. Разрешу прерывания по UDRE или проверю сам флаг при отправке данных и всё.
А вот с only R байтом "флагов" (на самом деле светодиоды управлялись) приходилось действительно использовать дополнительно байт, работать с ним, и периодически или по необходимости записывать его содержимое в тот only R байт.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.