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

Микроконтроллеры для начинающих

AVR_asm_Pad.rar Текстовый блокнот для написания программ для AVR на ассемблере с подсветкой синтаксиса и завершение автодополнения.

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


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

Доброго всем! Прошу помощи. Поставлена задача написания программы для СИФУ управляемого выпрямителя (3 фазы, мостовая схема, стабилизация тока, синхронизация). Выбор элементной базы не критичен. Опыт программирования только АВР, но совсем на начальном уровне. Где можно прочесть по поводу построения СИФУ? Может кто-то поделится алгоритмом? Заранее спасибо

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


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

Всем привет. Начал осваивать МК ATmega16.

Написал первую программу в AVR studio.

После подачи питания на МК запускается счетчик Т1 После того случается совпадение В, генерируется прерывание. Оно запускает АЦП. Когда АЦП закончило преобразование, оно тоже генерирует прерывание. Далее сохраняем результат и пытаемся его выдать по SPI. После того как последний байт передан все повторяется сначала. Но где - то что - то не работает. Вот сам код программы

 

 

.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
Нарушение п.3.4 Правил форума.

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


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

Но где - то что - то не работает. Вот сам код программы

Может быть - оно и будет работать... Но, недолго! Так, как это делаете Вы, работать с прерываниями - нельзя. Обработчик прерывания должен заканчиваться командой reti, иначе стек быстро переполниться: по каждому прерыванию в него заносится адрес возврата из прерывания!

OUTI OCR1AH,SetTimeWaitT1_H; С этим надо разобраться, без этих строк счетчик несчитает

OUTI OCR1AL,SetTimeWaitT1_L

Выбран режим счетчика 4. В этом режиме счетчик считает до значения OCR1A, сбрасывается в ноль и взводится флаг переполнения. Поэтому занести в регистр OCR1A что-то обязательно нужно. Воспользоваться лучше прерыванием по переполнению, а не по сравнению.

Ещё совет. Посмотрите как в примерах записывают в регистры значения при инициализации устройств МК и придерживайтесь такого же стиля: вместо Вашего

OUTI TCCR1B,SettingsTimT1_2

гораздо удобнее запись

OUTI TCCR1B, (1<<WGM12)|(1<<CS12)|(1<<CS10)

во всяком случае - удобнее для тех, кто захочет Вам помочь и посмотреть Вашу программу: не надо прыгать по программе вверх-вниз и заглядывать в документацию на МК.

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


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

Палыч, спасибо за ответ!!! Сам пишу программу первый раз, много не знаю. Вот второй вариант той же программы. Вроде как работает. Но мне не понятно, как формировать сигнал SS (SPI), или сигнал SS должен сам формироваться т. е. аппаратно. И как в этом режиме (SPI) передать сразу несколько байт, т. е. передать за одну посылку, или аппаратно контроллер такого сделать не может?


.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

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


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

1. sei перед reti - не нужно

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

ведь ваша фоновая программ не будет пустой как сейчас, а ваши макросы используют r25, поэтому как минимум надо было писать так

ISR_XXX:
    push r25
    ....
    pop r25
    reti

Вроде как работает. Но мне не понятно, как формировать сигнал SS (SPI), или сигнал SS должен сам формироваться т. е. аппаратно. И как в этом режиме (SPI) передать сразу несколько байт, т. е. передать за одну посылку, или аппаратно контроллер такого сделать не может?
SS формирует мастер. Настройте эту ножку на ввод от греха подальше (я не шучу).

Аппаратный интерфейс SPI у AVR может работать только с байтами.

Поэтому для передачи других данных, больших чем байт, программист должен немного подумать над тем, как их передать побайтно.

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


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

Но мне не понятно, как формировать сигнал SS (SPI), или сигнал SS должен сам формироваться т. е. аппаратно.
Сигнал SS в МК используется при работе SPI в режиме Slave. Поскольку у Вас SPI - в режиме Master, то эту ножку Вы можете использовать по своему усмотрению как Вам нужно/удобно. Если, соединённое с МК по SPI устройство требует определённого состояния сигнала на своей ноге SS, то необходимо подключить её к свободной ноге МК (не обязательно к SS МК), настроить её (ногу МК) на вывод и программно формировать на ней необходимый сигнал.

И как в этом режиме (SPI) передать сразу несколько байт, т. е. передать за одну посылку, или аппаратно контроллер такого сделать не может?
В SPI: одна посылка - один байт. Для передачи нескольких байт, обычно, организуют буфер, в который складывают байты готовые для передачи, и, по мере их передачи - последовательно выбирают их из буфера. Можно считать, что у Вас такой буфер из двух байт уже есть: acc_1 и acc_2. Необходимо завести некие указатели/флаги, по состоянию которых можно было бы судить в прерывании от SPI о том, что уже сделано и что нужно сделать (например, флаги: "передавался первый байт из двух", "вывод байтов закончен" или что-то подобное; или реализавать очередь типа FIFO с указателями на начало и конец очереди).

 

2. в обработчиках прерываний принято сохранять в стеке регистры, используемые в этом обработчике.
Добавлю, что помимо General Purpose Working Registers принято также сохранять регистр SREG...

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


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

Добавлю, что помимо General Purpose Working Registers принято также сохранять регистр SREG...
Ой, как же я забыл об этом упомянуть. Нет мне прощения:)

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


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

Зравствуйте! Подскажите как присвоить значение отдельным битам порта содержимое какой-нибудь переменной?

например:

 

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

post-56469-1276408422_thumb.jpgpost-56469-1276408430_thumb.jpg

Изменено пользователем Prevan

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


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

Есть плата, похожая на программатор - на плате есть FT232BM и установлен Attiny2313. При установке драйверов FT232BM появляется USB Serial Converter и виртуальный COM-порт.

 

Микросхема FT232BM по линиям от контактов #25 TXD и #24 RXD связана с Attiny2313 к контактам #2 PD0(RXD) и #3 PD1(TDX), через которые и собственно организован обмен данными. Вопрос: можно ли прошить МК через FT232BM, используя эти линии (похоже на UART?) - то есть ли возможность перепрошивать МК без подключения программатора (к SPI выводам МК), а только программными средствами по имеющимся линиям UART?

 

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


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

Вопрос: можно ли прошить МК через FT232BM, используя эти линии (похоже на UART?) - то есть ли возможность перепрошивать МК без подключения программатора (к SPI выводам МК), а только программными средствами по имеющимся линиям UART?

в обычном режиме невозможно перепрошивать МК через TXD/RXD,

теоретически для этого необходимо написать для Attiny2313 загрузчик flash через UART,

т.е. Вы посылаете через FT232BM байты , МК их получает и сам себя перепрошивает

Изменено пользователем rezident
Излишнее цитирование.

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


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

Я правильно понимаю, что обещание, что устройство будет программироваться только через USB, не выполнимо, то есть при производстве устройства всё равно придется хоть раз программировать МК по SPI каналу, а потом скреплять корпус?

 

update:

в обычном режиме невозможно перепрошивать МК через TXD/RXD,

теоретически для этого необходимо написать для Attiny2313 загрузчик flash через UART,

т.е. Вы посылаете через FT232BM байты , МК их получает и сам себя перепрошивает

разве у Attiny2313 есть возможность создания лодера? всего 2К памяти, насколько я понял описание

 

Изменено пользователем PDA

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


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

Я правильно понимаю, что обещание, что устройство будет программироваться только через USB, не выполнимо, то есть при производстве устройства всё равно придется хоть раз программировать МК по SPI каналу, а потом скреплять корпус?

первый раз конечно по SPI

update:разве у Attiny2313 есть возможность создания лодера? всего 2К памяти, насколько я понял описание

"The device provides a Self-Programming mechanism for downloading and uploading program code by the MCU itself."

2k мало, но вроде возможно

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


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

первый раз конечно по SPI
Тогда подскажите, возможно ли такая ситуация, что микросхема уже имеет какой-либо загрузчик? В моем случае, например, что микросхема уже имеет в себе загрузчик по UART?

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


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

Attiny2313 флеша маловато.. Есть ли на плате какие-либо кнопки? Если есть, можно попробовать зажать ее, перезапустить МК, и смотреть в терминал(или записать туда что-то), возможно, увидите бутлоадер.

Как вариант можно создать свой. Я использую(правда, для Mega AVR)AVR911, загружаю через Avr-Osp II. Очень удобно, код для меги16 занимает около 1кб.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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