Перейти к содержанию
    

Работа с отдельными битами под AVR Studio под С

Доброго времени суток , коллеги. Проблема в следующем. Пересмотрев достаточное количество материалов по программированию AVR на С, я так и не нашел ответа на сл. вопрос: как прочитать/изменить отдельный бит информации регистра? Для установления одного бита в лог. 1 есть библиотечная директива _BV(и та не везде работает). А как быть с чтением отдельных бит и установкой в ноль? На ассемблере ни для AVR, ни для PIC таких проблем не возникает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

byte |= (1<<bit) // - установка бита bit

byte &= ~(1<<bit) // - сброс бита bit

 

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

 

1<<bit можно заменить любой маской

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тоже в свое время "многа думаль". Додумался вот до чего:

 

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

 

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) тоже частенько встречаются.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для установления одного бита в лог. 1 есть библиотечная директива _BV(и та не везде работает).
Приведите пример не работы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Доброго времени суток , коллеги. Проблема в следующем. Пересмотрев достаточное количество материалов по программированию AVR на С, я так и не нашел ответа на сл. вопрос: как прочитать/изменить отдельный бит информации регистра? Для установления одного бита в лог. 1 есть библиотечная директива _BV(и та не везде работает). А как быть с чтением отдельных бит и установкой в ноль? На ассемблере ни для AVR, ни для PIC таких проблем не возникает.

Посмотрите на сахаре, эта тема вроде до сих пор обсуждается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Эта тема активно обсуждалась на форуме AVR в прошлом году. Спрашивающему поиск в помощь.

Присоединяюсь к реплике Сергея Борща. Может не был #define _BV определен или файл (avr/sfr_defs.h) подключен? Это не библиотечная функция.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сергей Борщ, Так, например, не хочет работать

 

PORTB=_BV(PORTB1);

 

mdmitry, Сергей Борщ,

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

#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, а теперь необходимы некоторые вычисл. мощности, которые проще сделать на МК, нежели на ПЛИС...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так, например, не хочет работать

PORTB=_BV(PORTB1);

Ммм... поясните пожалуйста термин "не хочет работать". Это выражение должно записать число 0x02 в PORTB. Затерев при этом предыдущее значение всех 8 битов.

 

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

 

ISR(TIMER0_OVF_vect)

Помню из детства: "однако, за время пути собака могла подрасти". Время идет, компилятор развивается. Книга была написана давно, примеры в ней относятся к компилятору версии 2005-2006 года (если память не изменяет).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

INTERRUPT(SIG_OWERFLOW1)

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

ISR(TIMER0_OVF_vect){

Имена SIG_xxxxx не рекомендуются к дальнейшему применению. (см. понятие "Deprecated features")

Упс, опередили.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня есть вот такой вопрос:

 

Как вы(обращение ко всем) работает с некоторой периферией у которой регистры устанавливаются по различным протоколам (USART, SPI, I2C) и имеют признаки only R/ only W/ RW, default-состояния отличные от 0?

Я встречал подходы с использованием массива shadow-регистров, но мне не понравился тот пример по изящности исполнения.

Если не жалко покажите свои наработки :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня есть вот такой вопрос...

С флагом UDRE в регистре состояния USART, который в 1 при старте, ничего никогда не делал. Разрешу прерывания по UDRE или проверю сам флаг при отправке данных и всё.

А вот с only R байтом "флагов" (на самом деле светодиоды управлялись) приходилось действительно использовать дополнительно байт, работать с ним, и периодически или по необходимости записывать его содержимое в тот only R байт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...