можно вообще сделать глобальную переменную и работать с ней, менять в подпрограмме оба порта, считывать тоже можно оба порта.
Просмотрел даташит на мегу8, в самом конце нашел адреса портов, но как то непонятно они записаны, например PORTB записан как 0x18 (0x38)
Это два адреса, абсолютный и относительный вся оперативная память находится в едином адресном пространстве некоторые функции типа чтения бита обращаются по относительному адресу(он занимает меньше бит при адресации) другие же полный адрес( чтение портов после возможного значения относительной адресации) это где нет числа в скобках.
Такие как PORTF в много ногих Мк.
vitalik_1984 писал(а):можно вообще сделать глобальную переменную и работать с ней, менять в подпрограмме оба порта, считывать тоже можно оба порта
Можно маленький пример, не совсем понимаю как это делать, ну к примеру объявляю глобальную переменную extern volatile unsigned char Name_Port, а дальше не совсем понятно, что в нее писать?
Работа избавляет нас от трех великих зол: скуки, порока, нужды. (Вольтер)
vitalik_1984 писал(а):
Это два адреса, абсолютный и относительный вся оперативная память находится в едином адресном пространстве некоторые функции типа чтения бита обращаются по относительному адресу(он занимает меньше бит при адресации) другие же полный адрес( чтение портов после возможного значения относительной адресации) это где нет числа в скобках.
Такие как PORTF в много ногих Мк.
не совсем понял, то есть если я хочу считать состояние пина или записать бит в регистр, мне нужно писать по относительному адресу, а если я хочу считать состояние регистра целиком или записать в него, мне нужно обращаться уже по абсолютному адресу так? а какой из них абсолютный и относительный? Тот что в скобках относительный?
Работа избавляет нас от трех великих зол: скуки, порока, нужды. (Вольтер)
Тут немножко вольное обращение с терминологией привело к недопониманию. "Относительный адрес" - это вольная интерпретация автора объяснения. Есть номер регистра в области ввода-вывода ( конечно, можно назвать его и "относительным", но это понятие многозначно : относительно указателя, отнсительно счетчика команд * ) -- и есть его абсолютный адрес в общем пространстве [ РОН - 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 .
спасибо за объяснение
вот переписал функцию калибровки сенсоров, с указателями на порты, чтоб не мудрить с опросом отдельных пинов, решил писать и читать весь регистр портов, правда не знаю будет ли работать вот эта строка?
ну я так и подумал что вы по этому поводу интересовались.
Я просто решил попробовать так, если не получится тогда уже буду выдумывать с подпрограммами.
Работа избавляет нас от трех великих зол: скуки, порока, нужды. (Вольтер)
разжуйте пожалуйста эти 2 строки, не совсем понятно почему знак указателя ставиться после типа данных, а не перед переменной указателем, и это тоже не понятно (unsigned char*)0x37; объясните пожалуйста.
Работа избавляет нас от трех великих зол: скуки, порока, нужды. (Вольтер)
можете и перед переменной поставить. в данном случае ничего не изменится.
int a, *b, c; // здесь a и c - переменные типа int, b - указатель на int
int* a, b, c; // здесь все переменные - указатели
(unsigned char*)0x37 - преобразование типа из int(по умолчанию) в адрес. некоторые компиляторы пропустят и без преобразования, предупреждение выдадут. CVAVR даст ошибку.
#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;
}
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 секции
Последний раз редактировалось vitalik_1984 Сб янв 05, 2013 20:22:44, всего редактировалось 1 раз.
не будет работать.
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 переключились не в той теме
Error: ...............\main.c(53): operand type 'sfrb' is incompatible with the '&' operator
Error: ...............\main.c(54): operand type 'sfrb' is incompatible with the '&' operator