CodeVision AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

можно вообще сделать глобальную переменную и работать с ней, менять в подпрограмме оба порта, считывать тоже можно оба порта.
Просмотрел даташит на мегу8, в самом конце нашел адреса портов, но как то непонятно они записаны, например PORTB записан как 0x18 (0x38)
Это два адреса, абсолютный и относительный вся оперативная память находится в едином адресном пространстве некоторые функции типа чтения бита обращаются по относительному адресу(он занимает меньше бит при адресации) другие же полный адрес( чтение портов после возможного значения относительной адресации) это где нет числа в скобках.
Такие как PORTF в много ногих Мк.
Контактная информация:
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 900
Зарегистрирован: Чт авг 27, 2009 20:09:01
Откуда: Приднестровье г.Бендеры

Сообщение mr4ester »

vitalik_1984 писал(а):можно вообще сделать глобальную переменную и работать с ней, менять в подпрограмме оба порта, считывать тоже можно оба порта
Можно маленький пример, не совсем понимаю как это делать, ну к примеру объявляю глобальную переменную extern volatile unsigned char Name_Port, а дальше не совсем понятно, что в нее писать?
Работа избавляет нас от трех великих зол: скуки, порока, нужды. (Вольтер)
Контактная информация:
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 900
Зарегистрирован: Чт авг 27, 2009 20:09:01
Откуда: Приднестровье г.Бендеры

Сообщение mr4ester »

vitalik_1984 писал(а): Это два адреса, абсолютный и относительный вся оперативная память находится в едином адресном пространстве некоторые функции типа чтения бита обращаются по относительному адресу(он занимает меньше бит при адресации) другие же полный адрес( чтение портов после возможного значения относительной адресации) это где нет числа в скобках.
Такие как PORTF в много ногих Мк.
не совсем понял, то есть если я хочу считать состояние пина или записать бит в регистр, мне нужно писать по относительному адресу, а если я хочу считать состояние регистра целиком или записать в него, мне нужно обращаться уже по абсолютному адресу так? а какой из них абсолютный и относительный? Тот что в скобках относительный?
Работа избавляет нас от трех великих зол: скуки, порока, нужды. (Вольтер)
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 6322
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

Тут немножко вольное обращение с терминологией привело к недопониманию. "Относительный адрес" - это вольная интерпретация автора объяснения. Есть номер регистра в области ввода-вывода ( конечно, можно назвать его и "относительным", но это понятие многозначно : относительно указателя, отнсительно счетчика команд * ) -- и есть его абсолютный адрес в общем пространстве [ РОН - I/O - память ] .

Так что целиком обращение к регистру В/В можно и так, и так
clr r16 ; Clear r16
out $18,r16 ; Write zeros to Port B
sts $38,r16 ; It is the same

а битовые операции операции с РОН и I/O предусмотрены только для этих областей, поэтому
работать с битами регистра I/O можно только по типу : sbi $1C,0 ; Set read bit in EECR

Кстати, у более новых МК Атмела для новых устройств нехватило адресов в области I/O, и они расположились в резервной области, и там уж только lds/sts и уж конечно, никаких sbi/cbi .

-------------------------------

* -- конечно, не для Гарвардской архитектуры
Реклама
Эиком - электронные компоненты и радиодетали
Держит паяльник хвостом
Аватара пользователя
Сообщения: 900
Зарегистрирован: Чт авг 27, 2009 20:09:01
Откуда: Приднестровье г.Бендеры

Сообщение mr4ester »

спасибо за объяснение :beer:
вот переписал функцию калибровки сенсоров, с указателями на порты, чтоб не мудрить с опросом отдельных пинов, решил писать и читать весь регистр портов, правда не знаю будет ли работать вот эта строка?

Код: Выделить всё

while((*Pin_X & i)==0); // жду пока не появится 1 на пине порта
исправленная функция, так как си я учу всего несколько недель, поэтому хотелось бы услышать конструктивную критику по коду.

Код: Выделить всё

// объявляю указатели портов
volatile char *Potr_X;
volatile char *Ddr_X;
volatile char *Pin_X;

// константы адресов портов
const char PortD_Addr = 0x12;
const char PortB_Addr = 0x18;
const char PinD_Addr = 0x10;
const char PinB_Addr = 0x16;
const char DdrD_Addr = 0x11;
const char DdrB_Addr = 0x17;

void Calibrate()  //Калибруем все сенсоры по очереди
{
unsigned char i=1,k=0;
Ddr_X = DdrD_Addr; // присваиваю указателю адрес порта D
Pin_X = PinD_Addr;

    while(i!=0)
    {
        TCNT1=0x0000;   // обнуляем счетный регистр
        TCCR1B=0x01; // разрешаю счет таймера1
        *Ddr_X &= ~i;// настраиваем пин порта на вход
        while((*Pin_X & i)==0); // жду пока не появится 1 на пине порта
        TCCR1B=0x00; //останавливаю таймер
        *Ddr_X |=i;  // конфигурирую пин на выход состояние Hi-Z
        SensorTimes[k]=TCNT1; // присваиваю время зарядки сенсора
        SensorHI[k]=SensorTimes[k]+70; //задаю верхний предел
        SensorLO[k]=SensorTimes[k]+20; // и нижний
        k++;                           // увеличиваю переменную на 1
        i<<=1;                         //сдвигаю 1 влево
        if (*Pin_X == 0x80)
        {
          i = 0x01;
          Ddr_X = DdrB_Addr;
          Pin_X = PinB_Addr;
        }
           if (k = 0x0d) // если к = 13 значит все 12 сенсоров откалиброванны, на порту B всего
           {
             i = 0x00;  // 4 сенсора, обнуляю чтоб выйти из цикла.
           }
    }
}
Еще такой вопрос, можно ли чтоб не создавать константы адресов, присваивать адрес порта таким образом

Код: Выделить всё

Ddr_X = &DDRD //  присвоить адрес регистра ddrd указателю Ddr_X 
Работа избавляет нас от трех великих зол: скуки, порока, нужды. (Вольтер)
Контактная информация:
Реклама
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

исправленная функция, ...
Этот код у Вас заработал ?
Контактная информация:
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 900
Зарегистрирован: Чт авг 27, 2009 20:09:01
Откуда: Приднестровье г.Бендеры

Сообщение mr4ester »

еще не проверял, разбираюсь пока с этой функцией, есть грубые ошибки, или криво написано что то?
Работа избавляет нас от трех великих зол: скуки, порока, нужды. (Вольтер)
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

есть грубые ошибки, или криво написано что то?
Я выше уже дважды писал о том, что с портами через указатель работать не получится. По этому и спросил.
Контактная информация:
Держит паяльник хвостом
Аватара пользователя
Сообщения: 900
Зарегистрирован: Чт авг 27, 2009 20:09:01
Откуда: Приднестровье г.Бендеры

Сообщение mr4ester »

ну я так и подумал что вы по этому поводу интересовались.
Я просто решил попробовать так, если не получится тогда уже буду выдумывать с подпрограммами.
Работа избавляет нас от трех великих зол: скуки, порока, нужды. (Вольтер)
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Не получится. Уже всё опробовано до Вас.
Контактная информация:
Первый раз сказал Мяу!
Сообщения: 22
Зарегистрирован: Вс июл 29, 2012 19:09:48

Сообщение RossiaForever »

Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

Аlex писал(а):Не получится. Уже всё опробовано до Вас.
а почему? у меня получилось ;)
для WinAVR:

Код: Выделить всё

#include <avr/io.h>
#include <avr/delay.h>

int main(void)
{
  uint8_t* ddrb = (uint8_t*)0x37;
  volatile uint8_t* portb = (uint8_t*)0x38;
  
  *ddrb = 0xFF;
  
  while(1)
  {
    *portb = 0xFF;
    _delay_ms(500);
    *portb = 0;
    _delay_ms(500);
  }
}
для CVAVR:

Код: Выделить всё

#include <mega8.h>
#include <delay.h>

void main(void)
{
  unsigned char* ddrb = (unsigned char*)0x37;
  volatile unsigned char* portb = (unsigned char*)0x38;
  
  *ddrb = 0xFF;
  
  while(1)
  {
    *portb = 0xFF;
    delay_ms(500);
    *portb = 0;
    delay_ms(500);
  }
}
Держит паяльник хвостом
Аватара пользователя
Сообщения: 900
Зарегистрирован: Чт авг 27, 2009 20:09:01
Откуда: Приднестровье г.Бендеры

Сообщение mr4ester »

Проверил в CVAVR + Proteus действительно работает, спасибо за правильный пример записи в регистр по адресу, только возник вопрос по синтаксису си,

Код: Выделить всё

unsigned char* ddrb = (unsigned char*)0x37;
  volatile unsigned char* portb = (unsigned char*)0x38;
  
разжуйте пожалуйста эти 2 строки, не совсем понятно почему знак указателя ставиться после типа данных, а не перед переменной указателем, и это тоже не понятно (unsigned char*)0x37; объясните пожалуйста.
Работа избавляет нас от трех великих зол: скуки, порока, нужды. (Вольтер)
Контактная информация:
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

можете и перед переменной поставить. в данном случае ничего не изменится.
int a, *b, c; // здесь a и c - переменные типа int, b - указатель на int
int* a, b, c; // здесь все переменные - указатели

(unsigned char*)0x37 - преобразование типа из int(по умолчанию) в адрес. некоторые компиляторы пропустят и без преобразования, предупреждение выдадут. CVAVR даст ошибку.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

a_skr,Молодчик только я бы немного по другому оформил

Код: Выделить всё

#include <avr/io.h>
#include <avr/delay.h>

int main(void)
{
  uint8_t* ptr_ddrb = (uint8_t*)&DDRB; //Тут чтобы не забивать голову константами адресов
  volatile uint8_t* ptr_portb = (uint8_t*)&PORTB;//И ptr_, чтобы было понятно, что это указатель
  
  *ptr_ddrb = 0xFF;
}
 
Кстати в файле sfr_defs.h Вот что прописано

Код: Выделить всё

iomx8.h
#define PORTB   _SFR_IO8 (0x05)
sfr_defs.h
#ifndef __SFR_OFFSET
/* Define as 0 before including this file for compatibility with old asm
   sources that don't subtract __SFR_OFFSET from symbolic I/O addresses.  */
#  if __AVR_ARCH__ >= 100
#    define __SFR_OFFSET 0x00
#  else
#    define __SFR_OFFSET 0x20
#  endif
#endif
#if _SFR_ASM_COMPAT
   #define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)
#else  /* !_SFR_ASM_COMPAT */
   #define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
#endif /* !_SFR_ASM_COMPAT */
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))<<< Вот аналогичное объявление :)
 
Обращение к регистрам производится через абсолютный адрес.
Jack_A писал(а):Тут немножко вольное обращение с терминологией привело к недопониманию. "Относительный адрес" - это вольная интерпретация автора объяснения. Есть номер регистра в области ввода-вывода ( конечно, можно назвать его и "относительным", но это понятие многозначно : относительно указателя, отнсительно счетчика команд * ) -- и есть его абсолютный адрес в общем пространстве [ РОН - I/O - память ] .
Простите запамятовал, сейчас посмотрел еще раз- в скобках абсолютный, то есть нумерация начинается после РОН 32,33, и тд.
Под относительным имел ввиду тот, что без скобок те начинается с нуля относительно последнего РОН нумерация ну или относительно начала I/O секции :dont_know:
Последний раз редактировалось vitalik_1984 Сб янв 05, 2013 20:22:44, всего редактировалось 1 раз.
Контактная информация:
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

не будет работать.
DDRB - уже есть доступ по адресу, а не определение адреса
в sfr_defs.h:
#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)

ps. что-то мы на WinAVR переключились не в той теме ;)
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

позволю себе создать второе сообщение подряд, но, раз тема про CVAVR, то такое:

Код: Выделить всё

  unsigned char *ptr_ddrb = &DDRB;
  volatile unsigned char *ptr_portb = &PORTB;
  *ptr_ddrb = 0xFF;
  *ptr_portb = 0x55;
вполне работоспособно
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

uint8_t* ddrb = (uint8_t*)&DDRB;
Вот так работает, может и костыль
a_skr писал(а):ps. что-то мы на WinAVR переключились не в той теме
Точно :oops:
a_skr ваш тоже робит :beer:
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

a_skr писал(а):позволю себе создать второе сообщение подряд, но, раз тема про CVAVR, то такое:

Код: Выделить всё

  
unsigned char *ptr_ddrb = &DDRB;
volatile unsigned char *ptr_portb = &PORTB;
вполне работоспособно
Error: ...............\main.c(53): operand type 'sfrb' is incompatible with the '&' operator
Error: ...............\main.c(54): operand type 'sfrb' is incompatible with the '&' operator
CVAVR v. 2.03.4
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

Работает в 2.05.3
Никто не мешает пользоваться адресом в виде числа :)
Контактная информация:
Ответить

Вернуться в «AVR»