|
|
  |
Микроконтроллеры для начинающих, AVR, PIC, FUJITSU |
|
|
|
Aug 19 2009, 06:20
|
Группа: Участник
Сообщений: 12
Регистрация: 3-01-06
Пользователь №: 12 790

|
AVR_asm_Pad.rar ( 53.98 килобайт )
Кол-во скачиваний: 213 Текстовый блокнот для написания программ для AVR на ассемблере с подсветкой синтаксиса и завершение автодополнения.
|
|
|
|
|
Dec 16 2009, 14:45
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 15-12-09
Пользователь №: 54 266

|
Всем привет. Начал осваивать МК ATmega16. Написал первую программу в AVR studio. После подачи питания на МК запускается счетчик Т1 После того случается совпадение В, генерируется прерывание. Оно запускает АЦП. Когда АЦП закончило преобразование, оно тоже генерирует прерывание. Далее сохраняем результат и пытаемся его выдать по SPI. После того как последний байт передан все повторяется сначала. Но где - то что - то не работает. Вот сам код программы CODE .INCLUDE "m16def.inc"
;*********Определяем макрос********* .MACRO OUTI LDI R25,@1 OUT @0,R25 .ENDMACRO
;*********Определяем константы********* .equ SettingsADC_1 = 0x8A .equ SettingsADC_2 = 0x60 .equ SettingsADC_3 = 0xB0 .equ SetPortCOut = 0xFF .equ SetFirstStatePortC = 0xFF .equ SetPortBOut = 0xFF .equ SetFirstStatePortB = 0x00 .equ SettingsTimT1_1 = 0x00 .equ SettingsTimT1_2 = 0x0D .equ SettingsTimT1_3 = 0x0C .equ SettingsSPI_1 = 0x10 .equ SettingsSPI_2 = 0x00
.equ SetTimeWaitT1_H = 0xFF; Сравнение в Т1 по этому значению .equ SetTimeWaitT1_L = 0xFF; Сравнение в Т1 по этому значению
;*********Назначим новые имена для регистров********* .def acc_1 = r16;Назначаем аккумулятор 1 .def acc_2 = r17;Назначаем аккумулятор 2
;*********Начальный адрес********* .CSEG .org $0000;Начальный адрес jmp RESET;Перепрыгиваем таблицу векторов
;*********Описание векторов прерываний********* .ORG INT0addr ; External Interrupt Request 0 RETI .ORG INT1addr ; External Interrupt Request 1 RETI .ORG OC2addr ; Timer/Counter2 Compare Match RETI .ORG OVF2addr ; Timer/Counter2 Overflow RETI .ORG ICP1addr ; Timer/Counter1 Capture Event RETI .ORG OC1Aaddr ; Timer/Counter1 Compare Match A RETI .ORG OC1Baddr ; Timer/Counter1 Compare Match B rjmp START_ADC .ORG OVF1addr ; Timer/Counter1 Overflow RETI .ORG OVF0addr ; Timer/Counter0 Overflow RETI .ORG SPIaddr ; Serial Transfer Complete RETI .ORG URXCaddr ; USART, Rx Complete RETI .ORG UDREaddr ; USART Data Register Empty RETI .ORG UTXCaddr ; USART, Tx Complete RETI .ORG ADCCaddr ; ADC Conversion Complete rjmp OUTDATA .ORG ERDYaddr ; EEPROM Ready RETI .ORG ACIaddr ; Analog Comparator RETI .ORG TWIaddr ; 2-wire Serial Interface RETI .ORG INT2addr ; External Interrupt Request 2 RETI .ORG OC0addr ; Timer/Counter0 Compare Match RETI .ORG SPMRaddr ; Store Program Memory Ready RETI
;*********Начало основной программы********* .ORG INT_VECTORS_SIZE; отсюда пошла сама программа RESET: OUTI SPL,low(RAMEND) ; Это мы загружаем в двубайтный регистр указателя OUTI SPH,High(RAMEND); стека SPH:SPL адрес конца оперативной памяти
;*********Инициализация АЦП********* OUTI ADCSRA,SettingsADC_1 OUTI ADMUX,SettingsADC_2 OUTI SFIOR,SettingsADC_3
;*********Инициализация портов********* OUTI DDRC,SetPortCOut ;Конфигурируем порт C как выход OUTI PORTC,SetFirstStatePortC;Начальное состояние порта 0 OUTI DDRB,SetPortBOut ;Конфигурируем порт B OUTI PORTB,SetFirstStatePortB;Начальное состояние порта 0
;*********Инициализация таймера/счетчика Т1********* OUTI TCCR1A,SettingsTimT1_1 OUTI TCCR1B,SettingsTimT1_2 OUTI TIMSK,SettingsTimT1_3
OUTI OCR1AH,SetTimeWaitT1_H; С этим надо разобраться, без этих строк счетчик несчитает OUTI OCR1AL,SetTimeWaitT1_L
OUTI OCR1BH,SetTimeWaitT1_H OUTI OCR1BL,SetTimeWaitT1_L
;*********Инициализация SPI********* ;OUTI SPCR,SettingsSPI_1;
MAIN: sei ; Общее разрешение прерываний nop rjmp MAIN
START_ADC: sei ; Общее разрешение прерываний sbi ADCSRA,ADSC WAIT: nop rjmp WAIT
OUTDATA: in acc_1,ADCH in acc_2,ADCL sbi SPCR,SPE sbi SPCR,MSTR out SPDR, acc_1 WAIT_TR_DATA_1: SBIS SPSR,SPIF rjmp WAIT_TR_DATA_1 out SPDR, acc_2 WAIT_TR_DATA_2: SBIS SPSR,SPIF rjmp WAIT_TR_DATA_2 rjmp MAIN Если не трудно покритикуйте
Сообщение отредактировал rezident - Dec 16 2009, 15:23
Причина редактирования: Нарушение п.3.4 Правил форума.
|
|
|
|
|
Dec 16 2009, 16:25
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Caruso @ Dec 16 2009, 17:45)  Но где - то что - то не работает. Вот сам код программы Может быть - оно и будет работать... Но, недолго! Так, как это делаете Вы, работать с прерываниями - нельзя. Обработчик прерывания должен заканчиваться командой reti, иначе стек быстро переполниться: по каждому прерыванию в него заносится адрес возврата из прерывания! Цитата OUTI OCR1AH,SetTimeWaitT1_H; С этим надо разобраться, без этих строк счетчик несчитает OUTI OCR1AL,SetTimeWaitT1_L Выбран режим счетчика 4. В этом режиме счетчик считает до значения OCR1A, сбрасывается в ноль и взводится флаг переполнения. Поэтому занести в регистр OCR1A что-то обязательно нужно. Воспользоваться лучше прерыванием по переполнению, а не по сравнению. Ещё совет. Посмотрите как в примерах записывают в регистры значения при инициализации устройств МК и придерживайтесь такого же стиля: вместо Вашего Код OUTI TCCR1B,SettingsTimT1_2 гораздо удобнее запись Код OUTI TCCR1B, (1<<WGM12)|(1<<CS12)|(1<<CS10) во всяком случае - удобнее для тех, кто захочет Вам помочь и посмотреть Вашу программу: не надо прыгать по программе вверх-вниз и заглядывать в документацию на МК.
|
|
|
|
|
Dec 22 2009, 07:19
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 15-12-09
Пользователь №: 54 266

|
Палыч, спасибо за ответ!!! Сам пишу программу первый раз, много не знаю. Вот второй вариант той же программы. Вроде как работает. Но мне не понятно, как формировать сигнал SS (SPI), или сигнал SS должен сам формироваться т. е. аппаратно. И как в этом режиме (SPI) передать сразу несколько байт, т. е. передать за одну посылку, или аппаратно контроллер такого сделать не может? CODE
.INCLUDE "m16def.inc"
;*********Определяем макрос********* .MACRO OUTI LDI R25,@1 OUT @0,R25 .ENDMACRO
.MACRO SETBIT IN R25,@0 SBR R25,(1<<@1) OUT @0,R25 .ENDMACRO
;*********Определяем константы********* .equ TimeWait_H = 0x00 .equ TimeWait_L = 0x00 .equ SettingsSPI_1 = 0x10 .equ SettingsSPI_2 = 0x00
;*********Назначим новые имена для регистров********* .def acc_1 = r16 ;Назначаем аккумулятор 1 .def acc_2 = r17 ;Назначаем аккумулятор 2
;*********Начальный адрес********* .CSEG .org $0000 ;Начальный адрес JMP RESET ;Перепрыгиваем таблицу векторов
;*********Описание векторов прерываний********* .ORG INT0addr ; External Interrupt Request 0 RETI .ORG INT1addr ; External Interrupt Request 1 RETI .ORG OC2addr ; Timer/Counter2 Compare Match RETI .ORG OVF2addr ; Timer/Counter2 Overflow RETI .ORG ICP1addr ; Timer/Counter1 Capture Event RETI .ORG OC1Aaddr ; Timer/Counter1 Compare Match A RETI .ORG OC1Baddr ; Timer/Counter1 Compare Match B RETI .ORG OVF1addr ; Timer/Counter1 Overflow RJMP STARTADC .ORG OVF0addr ; Timer/Counter0 Overflow RETI .ORG SPIaddr ; Serial Transfer Complete RJMP TRANSMISSIONSPI2BYTE .ORG URXCaddr ; USART, Rx Complete RETI .ORG UDREaddr ; USART Data Register Empty RETI .ORG UTXCaddr ; USART, Tx Complete RETI .ORG ADCCaddr ; ADC Conversion Complete RJMP TRANSMISSIONSPI1BYTE .ORG ERDYaddr ; EEPROM Ready RETI .ORG ACIaddr ; Analog Comparator RETI .ORG TWIaddr ; 2-wire Serial Interface RETI .ORG INT2addr ; External Interrupt Request 2 RETI .ORG OC0addr ; Timer/Counter0 Compare Match RETI .ORG SPMRaddr ; Store Program Memory Ready RETI
;*********Начало основной программы********* .ORG INT_VECTORS_SIZE ; отсюда пошла сама программа RESET: OUTI SPL,low(RAMEND) ; Это мы загружаем в двубайтный регистр указателя OUTI SPH,High(RAMEND) ; стека SPH:SPL адрес конца оперативной памяти
;*********Инициализация АЦП*********
OUTI ADCSRA, (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0) ;АЦП разрешен, прерывание от него тоже, ;коэффициент делитедя 128 OUTI ADMUX, (1<<REFS0)|(1<<ADLAR) ;AVcc - источник опорного напряжения, ;результат преобразования выравниваем влево OUTI SFIOR, (1<<ADHSM) ;Увеличиваем скорость АЦП
;*********Инициализация портов*********
OUTI PORTC, (1<<PORTC0)|(1<<PORTC1)|(1<<PORTC2)|(1<<PORTC3)|(1<<PORTC4)|(1<<PORTC5)|(1<<PORTC6)|(1<<PORTC7) ;Начальное состояние порта C 1 OUTI DDRC, (1<<DDC0)|(1<<DDC1)|(1<<DDC2)|(1<<DDC3)|(1<<DDC4)|(1<<DDC5)|(1<<DDC6)|(1<<DDC7) ;Конфигурируем порт C как выход OUTI PORTB, (1<<PORTB0)|(1<<PORTB1)|(1<<PORTB2)|(1<<PORTB3)|(1<<PORTB4)|(1<<PORTB5)|(1<<PORTB6)|(1<<PORTB7) ;Начальное состояние порта B 1 OUTI DDRB, (1<<DDB0)|(1<<DDB1)|(1<<DDB2)|(1<<DDB3)|(1<<DDB4)|(1<<DDB5)|(1<<DDB6)|(1<<DDB7) ;Конфигурируем порт B как выход
;*********Инициализация таймера/счетчика Т1********* OUTI TCCR1B, (1<<CS11) ;Режим работы 0 (Normal), частоту делим на 8
OUTI TIMSK, (1<<TOIE1) ;Разрешение прерывания таймера Т1 по переполнению
OUTI TCNT1H, TimeWait_H ;задаем начальное значение счетчика (старший байт) OUTI TCNT1L, TimeWait_L ;задаем начальное значение счетчика (младший байт)
;*********Инициализация SPI********* OUTI SPCR, (1<<SPIE)|(1<<MSTR)|(1<<SPI2X)|(1<<SPR1)|(1<<SPR0) ;Разрешаем прерывание SPI, выбран режим мастера, скорость передачи делим на 64
;*********Сама программа*********
SEI MAIN: NOP RJMP MAIN
STARTADC: SETBIT ADCSRA,ADSC ;Старт АЦП OUTI TCNT1H, TimeWait_H ;повторно задаем начальное значение счетчика (старший байт) для синхронизации OUTI TCNT1L, TimeWait_L ;повторно задаем начальное значение счетчика (младший байт) SEI ;разрешаем прерывания RETI
TRANSMISSIONSPI1BYTE: IN acc_1,ADCH ;Сохраняем значение АЦП (старший байт) IN acc_2,ADCL ;Сохраняем значение АЦП (младший байт) SETBIT SPCR,SPE ;Включение SPI OUT SPDR,acc_1 ;Заносим в регистр данных старший байт АЦП OUTI TCNT1H, TimeWait_H ;повторно задаем начальное значение счетчика (старший байт) для синхронизации OUTI TCNT1L, TimeWait_L ;повторно задаем начальное значение счетчика (младший байт) SEI RETI
TRANSMISSIONSPI2BYTE: SETBIT SPCR,SPE ;Включение SPI OUT SPDR,acc_2 ;Заносим в регистр данных младщий байт АЦП OUTI TCNT1H, TimeWait_H ;повторно задаем начальное значение счетчика (старший байт) для синхронизации OUTI TCNT1L, TimeWait_L ;повторно задаем начальное значение счетчика (младший байт) SEI RETI
|
|
|
|
|
Dec 22 2009, 18:17
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
1. sei перед reti - не нужно 2. в обработчиках прерываний принято сохранять в стеке регистры, используемые в этом обработчике. ведь ваша фоновая программ не будет пустой как сейчас, а ваши макросы используют r25, поэтому как минимум надо было писать так Код ISR_XXX: push r25 .... pop r25 reti Цитата(Caruso @ Dec 22 2009, 10:19)  Вроде как работает. Но мне не понятно, как формировать сигнал SS (SPI), или сигнал SS должен сам формироваться т. е. аппаратно. И как в этом режиме (SPI) передать сразу несколько байт, т. е. передать за одну посылку, или аппаратно контроллер такого сделать не может? SS формирует мастер. Настройте эту ножку на ввод от греха подальше (я не шучу). Аппаратный интерфейс SPI у AVR может работать только с байтами. Поэтому для передачи других данных, больших чем байт, программист должен немного подумать над тем, как их передать побайтно.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Dec 23 2009, 08:27
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Caruso @ Dec 22 2009, 10:19)  Но мне не понятно, как формировать сигнал SS (SPI), или сигнал SS должен сам формироваться т. е. аппаратно. Сигнал SS в МК используется при работе SPI в режиме Slave. Поскольку у Вас SPI - в режиме Master, то эту ножку Вы можете использовать по своему усмотрению как Вам нужно/удобно. Если, соединённое с МК по SPI устройство требует определённого состояния сигнала на своей ноге SS, то необходимо подключить её к свободной ноге МК (не обязательно к SS МК), настроить её (ногу МК) на вывод и программно формировать на ней необходимый сигнал. Цитата(Caruso @ Dec 22 2009, 10:19)  И как в этом режиме (SPI) передать сразу несколько байт, т. е. передать за одну посылку, или аппаратно контроллер такого сделать не может? В SPI: одна посылка - один байт. Для передачи нескольких байт, обычно, организуют буфер, в который складывают байты готовые для передачи, и, по мере их передачи - последовательно выбирают их из буфера. Можно считать, что у Вас такой буфер из двух байт уже есть: acc_1 и acc_2. Необходимо завести некие указатели/флаги, по состоянию которых можно было бы судить в прерывании от SPI о том, что уже сделано и что нужно сделать (например, флаги: "передавался первый байт из двух", "вывод байтов закончен" или что-то подобное; или реализавать очередь типа FIFO с указателями на начало и конец очереди). Цитата(demiurg_spb @ Dec 22 2009, 21:17)  2. в обработчиках прерываний принято сохранять в стеке регистры, используемые в этом обработчике. Добавлю, что помимо General Purpose Working Registers принято также сохранять регистр SREG...
|
|
|
|
|
Jun 13 2010, 05:54
|
Участник

Группа: Участник
Сообщений: 15
Регистрация: 7-04-10
Пользователь №: 56 469

|
Зравствуйте! Подскажите как присвоить значение отдельным битам порта содержимое какой-нибудь переменной? например: out PORTD,temp ;будет просто установлено значение переменной temp в порт D а мне надо в порт С на 3ю ножку установить значение такое же как на 6м бите перменной temp и таким же образом раскидать другие переменные. И наоборот. Как можно сделать обратную операцию, т.е. из разных битов портов составить содержимое переменной temp? например: in temp,PINC ;будет просто скопировано значение состояния порта С переменную temp Дело в том, что мне необходимо "мягко" изменить код программы, не прибегаю к полному переписанию кода программы. Переменные, указанные в программе работают со старым подключением проводов к ножкам МК. т.е. мне надо будет изменить следующий код: out PORTD,scancod clc ldi rots,4 in temp,PINC где: PD0 <->PD4 PD1 <->PD5 PD4 <->PC0 PD5 <->PC1 PD6 <->PC2 PD7 <->PC3
Сообщение отредактировал Prevan - Jun 13 2010, 05:54
|
|
|
|
|
Jul 27 2010, 12:48
|
Участник

Группа: Участник
Сообщений: 24
Регистрация: 6-05-06
Из: Москва
Пользователь №: 16 848

|
Цитата(PDA @ Jul 27 2010, 16:32)  Вопрос: можно ли прошить МК через FT232BM, используя эти линии (похоже на UART?) - то есть ли возможность перепрошивать МК без подключения программатора (к SPI выводам МК), а только программными средствами по имеющимся линиям UART? в обычном режиме невозможно перепрошивать МК через TXD/RXD, теоретически для этого необходимо написать для Attiny2313 загрузчик flash через UART, т.е. Вы посылаете через FT232BM байты , МК их получает и сам себя перепрошивает
Сообщение отредактировал rezident - Jul 27 2010, 13:48
Причина редактирования: Излишнее цитирование.
|
|
|
|
|
Jul 27 2010, 12:53
|

Участник

Группа: Участник
Сообщений: 46
Регистрация: 16-10-09
Из: msk
Пользователь №: 53 001

|
Я правильно понимаю, что обещание, что устройство будет программироваться только через USB, не выполнимо, то есть при производстве устройства всё равно придется хоть раз программировать МК по SPI каналу, а потом скреплять корпус? update: Цитата(Дмитрий К. @ Jul 27 2010, 16:48)  в обычном режиме невозможно перепрошивать МК через TXD/RXD, теоретически для этого необходимо написать для Attiny2313 загрузчик flash через UART, т.е. Вы посылаете через FT232BM байты , МК их получает и сам себя перепрошивает разве у Attiny2313 есть возможность создания лодера? всего 2К памяти, насколько я понял описание
Сообщение отредактировал PDA - Jul 27 2010, 13:19
|
|
|
|
|
Jul 27 2010, 13:35
|
Участник

Группа: Участник
Сообщений: 24
Регистрация: 6-05-06
Из: Москва
Пользователь №: 16 848

|
Цитата(PDA @ Jul 27 2010, 16:53)  Я правильно понимаю, что обещание, что устройство будет программироваться только через USB, не выполнимо, то есть при производстве устройства всё равно придется хоть раз программировать МК по SPI каналу, а потом скреплять корпус? первый раз конечно по SPI Цитата(PDA @ Jul 27 2010, 16:53)  update:разве у Attiny2313 есть возможность создания лодера? всего 2К памяти, насколько я понял описание "The device provides a Self-Programming mechanism for downloading and uploading program code by the MCU itself." 2k мало, но вроде возможно
|
|
|
|
|
Jul 27 2010, 14:37
|

Участник

Группа: Участник
Сообщений: 46
Регистрация: 16-10-09
Из: msk
Пользователь №: 53 001

|
Цитата первый раз конечно по SPI Тогда подскажите, возможно ли такая ситуация, что микросхема уже имеет какой-либо загрузчик? В моем случае, например, что микросхема уже имеет в себе загрузчик по UART?
|
|
|
|
|
  |
4 чел. читают эту тему (гостей: 4, скрытых пользователей: 0)
Пользователей: 0
|
|
|