Главная › Форумы › Программирование микроконтроллеров › Программирование МК AVR
Помечено: AVR
- В этой теме 53 ответа, 40 участников, последнее обновление 7 месяцев, 3 недели назад сделано
Solder.
-
АвторСообщения
-
Ноябрь 25, 2020 в 9:28 дп #22271
cedric69
УчастникЗдравствуйте! Нужна помощь. Пробую задействовать два входа АЦП на тини13 и чтоб замеры на каждом в пине соответствовали действиям на двух соответствующих выходах. Столкнулся с проблемой — не могу сохранить значения . Значения АЦП вмешиваются во все функции дрыгая не своими ногами. Как сохранить значение предназначенное для отдельной функции и соответственно переписать именно когда дойдет очередь. Очередь я считаю по if (ADCSRA&(1<<ADSC)) и скажем если X четное то «направо» нечетное «налево» За ранее спасибо.
Декабрь 24, 2020 в 1:14 пп #22291Zhenya
УчастникЗдравствуйте! Нужна помощь по индикации, но в 3 разряда. Комментарские варинты не работают, а код ниже хорошо показывает 2 разряда.
12345678910ISR (TIMER1_COMPA_vect) //Верный для двух разрядов{if(n_count==0) {PORTD&=~(1<<PORTD0);PORTD|=(1<<PORTD1);segchar(R1);}if(n_count==1) {PORTD&=~(1<<PORTD1);PORTD|=(1<<PORTD0);segchar(R2);}if(n_count==2) {segchar(R3);}n_count++;if (n_count>1) n_count=0;}Август 2, 2021 в 7:32 дп #22392oleg5672
УчастникЗдравствуйте друзья нужна помощь подправить код ИК-приёмник на Attiny13. При долговременном нажатии на кнопку пульта светодиод на выходе работает в тригерном режиме , надо поправить код чтоб светодиод при долговременном(удержание кнопки пульта) нажатии на кнопку пульта горел постоянно . Ниже прилагаю код написанный на assembler
;— http://radiohlam.ru — собери сам, помоги собрать другу
;——————————————————————
.device ATtiny13
.include «tn13def.inc»
.list;— определ¤ем свои переменные
.def w=r16 ; это будет наш аккумул¤тор
.def MBC=r17 ; старший байт посылки
.def LBC=r18 ; младший байт посылки
.def Sch=r19 ; счЄтчик прин¤тых бит
.def C_time=r20; текущее значение таймера
.def H_time=r21; 3/4 бита
;— определ¤ем константы
.equ Sys=29 ; номер системы
.equ CMD_1=1 ; 000001 код команды=1
.equ CMD_2=2 ; 000010 код команды=2
.equ CMD_3=3 ; 000011 код команды=3
.equ CMD_4=4 ; 000100 код команды=4
.equ Delay = 100
;— »спользуемые регистры
; SPL — указатель вершины стека
; ACSR — управление компаратором
; DDRB — направление работы ног
; PORTB — выходы порта
; PCMSK — разрешение прерываний на отдельных входах
; GIMSK — общее разрешение прерываний по входам
; GTCCR — сброс предделител¤
; TCCR0B — управление таймером
; TIMSK0 — прерывани¤ от таймера
; PB0 — выход D3, PB1- выход D2, PB2- выход D1, PB3 — вход, PB4 — выход D4
;— начало программного кода
.cseg
.org 0
rjmp Init ; переход на начало программы
;— вектора прерываний
reti ; INT0
rjmp Pch ; Pin Change
rjmp Timer ; Timer
reti ; EEPROM
reti ; comparator
reti ; timer compare match A
reti ; timer compare match B
reti ; watchdog
reti ; ADC
;— начало программы
Init: ldi w,RAMEND ; устанавливаем указатель вершины
out SPL,w ; стека на старший байт RAM
sbi ACSR,7 ; выключаем компаратор
ldi w,0b00010111 ; определ¤ем входы и выходы порта
out DDRB,w
ldi w,0b11101000 ; включаем подт¤гивающие резисторы
out PORTB,w ; и определ¤ем начальное состо¤ние выходов
;— разрешить прерывани¤ от таймера (пока он не запущен — прерывани¤ всЄ равно не будет)
ldi w,0b00000010
out TIMSK0,w ; разрешить прерывани¤ от таймера
;— ќбнул¤ем счЄтчик и регистр флагов
Reset: in w,PORTB ; читаем порт
clr Sch
clt ; сбрасываем флаг “
;— разрешить прерывание от входов
ldi w,0b00100000
out GIMSK,w ; разрешаем прерывание от входов
;— разрешить прерывани¤ на входе PB3
Start: ldi w,0b00100000
out GIFR,w ; сбросить флаг прерываний от входов
ldi w,0b00001000
out PCMSK,w ; разрешаем прерывани¤ на входе PB3
sei ; разрешить глобальные прерывани¤
Scan: nop
rjmp Scan
;— ќЅ–јЅќ“„» ѕ–?–џ¬јЌ»я ѕќ ¬’ќ?”
;— инициализируем счЄтчик, адр.бита, пров.рег., адр.рег.записи
Pch: tst Sch ; счЄтчик =0?
brne Next
Nachalo: sbic PINB,3 ; если на входе низкий уровень — пропускаем команду
reti ; это не приЄм — выходим
ldi w,0b00000001
out GTCCR,w ; сбросить предделитель
ldi w,0b00000100
out TCCR0B,w ; запустить таймер с делителем на 256
sec ; подн¤ть carry flag
rol LBC
rol MBC
inc Sch
reti
Next: in C_time,TCNT0 ; читаем значение таймера
clr w
out TCNT0,w ; перезапускаем таймер
cpi Sch,1 ; Sch=1?
brne Next2
Next1: mov H_time,C_time
lsr C_time ; находим четверть бита
add H_time,C_time ; находим 3/4 бита
set ; ставим флаг пропуска (T в регистре SREG)
sec
rol LBC
rol MBC
inc Sch ; увеличиваем счЄтчик
reti
Next2: brts Not_Signed_FRont
Signed_Front:
cp C_time,H_time
brsh Long_time
Short_time: set ; установить признак пропуска
clc
sbrc LBC,0 ; пропустить, если прошлоне значение = 0
sec
rjmp Zapis_bita
Long_time: clc ; принимаемый бит инвертирован, по отношению к последнему
sbrs LBC,0 ; пропустить, если прошлое значение = 1
sec
Zapis_bita: rol LBC
rol MBC
inc Sch
cpi Sch,14
breq rab_chast
reti
Not_Signed_Front:
clt
reti
;— ќЅ–јЅќ“„» ѕ–?–џ¬јЌ»я ќ“ “ј…ћ?–ј
Timer: clr w
out TCCR0B,w ; выключить таймер
pop w ; очищаем стек
pop w
rjmp Reset ; ресетимс¤;— –јЅќ„јя „ј—“№
;— ѕроверка номера системы и команды
rab_chast: clr w
out TCCR0B,w ; выключить таймер
out TCNT0,w ; сбросить таймер
pop w ; очищаем стек
pop w
clc
rol LBC ; сдвигаем всЄ, кроме номера команды в MBC
rol MBC
clc
rol LBC
rol MBC
lsr LBC ; выравниваем номер команды младшим битом к
lsr LBC ; младшему биту байта
in w,PORTB ; читаем порт B
cpi LBC,CMD_1
breq Button1
cpi LBC,CMD_2
breq Button2
cpi LBC,CMD_3
breq Button3
cpi LBC,CMD_4
breq Button4
rjmp Reset
Button1: ldi Sch,0b00000001
eor w,Sch ; инвертируем нулевой бит
out PORTB,w
rjmp Thats_all
Button2: ldi Sch,0b00000010
eor w,Sch ; инвертируем первый бит
out PORTB,w
rjmp Thats_all
Button3: ldi Sch,0b00000100
eor w,Sch ; инвертируем второй бит
out PORTB,w
rjmp Thats_all
Button4: ldi Sch,0b00010000
eor w,Sch ; инвертируем четвЄртый бит
out PORTB,w
Thats_all: rcall Pause
rjmp Reset
Pause: ldi R22, Delay ; загрузка константы для задержки в регистр R22
WLoop0:
ldi R23, 0x28 ; загружаем число 40 (0x28) в регистр R23
WLoop1:
ldi R24, 0xFF ; загружаем число 255 (0xFF) в регистр R24
WLoop2:
dec R24 ; уменьшаем значение в регистре R24 на 1
brne WLoop2 ; возврат к WLoop2 если значение в R24 не равно 0
dec R23 ; уменьшаем значение в регистре R23 на 1
brne WLoop1 ; возврат к WLoop1 если значение в R23 не равно 0
dec R22 ; уменьшаем значение в регистре R22 на 1
brne WLoop0 ; возврат к WLoop0 если значение в R22 не равно 0
eor w,Sch ; инвертируем второй бит
out PORTB,w
ret ; возврат из подпрограммы PauseОктябрь 10, 2021 в 6:14 пп #22565Ilya3145456
УчастникЗдравствуйте. Помогите считать температуру с датчика LMT01. Датчик подключен к ножке внешнего прерывания. При попытках считать импульсы возникла проблема с таймингами между периодами импульсов и паузой.
Ноябрь 6, 2021 в 1:49 пп #22577Andry_EXOSpace
УчастникЗдравствуйте! Во-первых, большое спасибо вам за сайт!!!
Но, Изучая урок 22 часть 2. ни как не могу понять:
Ни как не могу понять как получили значение с АЦП!
return (unsigned int) ADC; как это работает?
где обработка регистров ADCH и ADCL. как в 3 части урока?
Поясните пожалуйста этот момент.Январь 27, 2022 в 7:06 пп #22691megger380
УчастникAndry_EXOSpace, просто возвращаем значение 10 бит регистра ADC целиком, даташит стр.208.
Апрель 7, 2022 в 3:10 дп #22904Vlakar
УчастникДля разработки устройства на Atmega 8 необходимо задействовать ШИМ (PB1-PB3)и аппаратный SPI (PB1-PB4) но вся беда в том что они занимают одни и те же ноги
можно как то реализовать их параллельную работу или нет ?
И вообще это реализуемо ?Апрель 12, 2022 в 11:58 дп #22965Andry_EXOSpace
УчастникМожет по очереди их использовать? или аппаратный SPI?
Октябрь 20, 2022 в 6:15 пп #24254Solder
УчастникПриветствую всех форумчан и автора сайта! Изучаю программирование Atmega8 на языке С. Пытаюсь передать температуру измеренную DS18B20 с помощью модуля NRF24L01, по мотивам урока 105 «NRF24L01. Передаём данные». Вот кусок программы на передающей части в основной программе:
…
int main (void){
…
while(1)
{
if (TEMPER_Transmit(buf1))
{
USART_Transmit(buf1[0]);
USART_Transmit(buf1[1]);
NRF24L01_Send(buf1);
}
_delay_ms(1000);
}
}
Тут я думаю, все нормально, USART в терминальной программе показывает два байта со значением температуры (например 8А 01), значения меняются при нагреве ds18b20.В приемной части кусок программы такой:
…
#define TX_PLOAD_WIDTH 2
uint8_t RX_BUF[TX_PLOAD_WIDTH] = {0};
…
int main(void){
…
while(1)
{
uint8_t status=0x01;
if (BitIsClear(PINC,IRQ)) //если нога IRQ упала, значит надо выяснить, может принят байт?
{
status = NRF24_ReadReg(STATUS); //прочитали статус регистр
_delay_us(10);
status = NRF24_ReadReg(STATUS);
if(status & 0x40)
{
NRF24_Read_Buf(RD_RX_PLOAD,RX_BUF,TX_PLOAD_WIDTH);Temp_L = RX_BUF[0];
Temp_H = RX_BUF[1];
USART_Transmit(Temp_L);
USART_Transmit(Temp_H);
…
…// здесь подпрограмма вывода показаний на экран
}
}
Модуль NRF24L01 работает, принимает что-то, USART на терминальной программе показывает постоянные цифры 64 65, снова 64 65 и так далее одно и тоже, значение которой не меняется при изменении температуры в передающей части. Прошу помощи, что в коде не так, как в принимающей части подправить, чтобы получить правильную информацию? -
АвторСообщения
-
АвторСообщения
-
Здравствуйте! Нужна помощь. Пробую задействовать два входа АЦП на тини13 и чтоб замеры на каждом в пине соответствовали действиям на двух соответствующих выходах. Столкнулся с проблемой — не могу сохранить значения . Значения АЦП вмешиваются во все функции дрыгая не своими ногами. Как сохранить значение предназначенное для отдельной функции и соответственно переписать именно когда дойдет очередь. Очередь я считаю по if (ADCSRA&(1<<ADSC)) и скажем если X четное то «направо» нечетное «налево» За ранее спасибо.
Здравствуйте! Нужна помощь по индикации, но в 3 разряда. Комментарские варинты не работают, а код ниже хорошо показывает 2 разряда.
12345678910ISR (TIMER1_COMPA_vect) //Верный для двух разрядов{if(n_count==0) {PORTD&=~(1<<PORTD0);PORTD|=(1<<PORTD1);segchar(R1);}if(n_count==1) {PORTD&=~(1<<PORTD1);PORTD|=(1<<PORTD0);segchar(R2);}if(n_count==2) {segchar(R3);}n_count++;if (n_count>1) n_count=0;}Здравствуйте друзья нужна помощь подправить код ИК-приёмник на Attiny13. При долговременном нажатии на кнопку пульта светодиод на выходе работает в тригерном режиме , надо поправить код чтоб светодиод при долговременном(удержание кнопки пульта) нажатии на кнопку пульта горел постоянно . Ниже прилагаю код написанный на assembler
;— http://radiohlam.ru — собери сам, помоги собрать другу
;——————————————————————
.device ATtiny13
.include «tn13def.inc»
.list;— определ¤ем свои переменные
.def w=r16 ; это будет наш аккумул¤тор
.def MBC=r17 ; старший байт посылки
.def LBC=r18 ; младший байт посылки
.def Sch=r19 ; счЄтчик прин¤тых бит
.def C_time=r20; текущее значение таймера
.def H_time=r21; 3/4 бита
;— определ¤ем константы
.equ Sys=29 ; номер системы
.equ CMD_1=1 ; 000001 код команды=1
.equ CMD_2=2 ; 000010 код команды=2
.equ CMD_3=3 ; 000011 код команды=3
.equ CMD_4=4 ; 000100 код команды=4
.equ Delay = 100
;— »спользуемые регистры
; SPL — указатель вершины стека
; ACSR — управление компаратором
; DDRB — направление работы ног
; PORTB — выходы порта
; PCMSK — разрешение прерываний на отдельных входах
; GIMSK — общее разрешение прерываний по входам
; GTCCR — сброс предделител¤
; TCCR0B — управление таймером
; TIMSK0 — прерывани¤ от таймера
; PB0 — выход D3, PB1- выход D2, PB2- выход D1, PB3 — вход, PB4 — выход D4
;— начало программного кода
.cseg
.org 0
rjmp Init ; переход на начало программы
;— вектора прерываний
reti ; INT0
rjmp Pch ; Pin Change
rjmp Timer ; Timer
reti ; EEPROM
reti ; comparator
reti ; timer compare match A
reti ; timer compare match B
reti ; watchdog
reti ; ADC
;— начало программы
Init: ldi w,RAMEND ; устанавливаем указатель вершины
out SPL,w ; стека на старший байт RAM
sbi ACSR,7 ; выключаем компаратор
ldi w,0b00010111 ; определ¤ем входы и выходы порта
out DDRB,w
ldi w,0b11101000 ; включаем подт¤гивающие резисторы
out PORTB,w ; и определ¤ем начальное состо¤ние выходов
;— разрешить прерывани¤ от таймера (пока он не запущен — прерывани¤ всЄ равно не будет)
ldi w,0b00000010
out TIMSK0,w ; разрешить прерывани¤ от таймера
;— ќбнул¤ем счЄтчик и регистр флагов
Reset: in w,PORTB ; читаем порт
clr Sch
clt ; сбрасываем флаг “
;— разрешить прерывание от входов
ldi w,0b00100000
out GIMSK,w ; разрешаем прерывание от входов
;— разрешить прерывани¤ на входе PB3
Start: ldi w,0b00100000
out GIFR,w ; сбросить флаг прерываний от входов
ldi w,0b00001000
out PCMSK,w ; разрешаем прерывани¤ на входе PB3
sei ; разрешить глобальные прерывани¤
Scan: nop
rjmp Scan
;— ќЅ–јЅќ“„» ѕ–?–џ¬јЌ»я ѕќ ¬’ќ?”
;— инициализируем счЄтчик, адр.бита, пров.рег., адр.рег.записи
Pch: tst Sch ; счЄтчик =0?
brne Next
Nachalo: sbic PINB,3 ; если на входе низкий уровень — пропускаем команду
reti ; это не приЄм — выходим
ldi w,0b00000001
out GTCCR,w ; сбросить предделитель
ldi w,0b00000100
out TCCR0B,w ; запустить таймер с делителем на 256
sec ; подн¤ть carry flag
rol LBC
rol MBC
inc Sch
reti
Next: in C_time,TCNT0 ; читаем значение таймера
clr w
out TCNT0,w ; перезапускаем таймер
cpi Sch,1 ; Sch=1?
brne Next2
Next1: mov H_time,C_time
lsr C_time ; находим четверть бита
add H_time,C_time ; находим 3/4 бита
set ; ставим флаг пропуска (T в регистре SREG)
sec
rol LBC
rol MBC
inc Sch ; увеличиваем счЄтчик
reti
Next2: brts Not_Signed_FRont
Signed_Front:
cp C_time,H_time
brsh Long_time
Short_time: set ; установить признак пропуска
clc
sbrc LBC,0 ; пропустить, если прошлоне значение = 0
sec
rjmp Zapis_bita
Long_time: clc ; принимаемый бит инвертирован, по отношению к последнему
sbrs LBC,0 ; пропустить, если прошлое значение = 1
sec
Zapis_bita: rol LBC
rol MBC
inc Sch
cpi Sch,14
breq rab_chast
reti
Not_Signed_Front:
clt
reti
;— ќЅ–јЅќ“„» ѕ–?–џ¬јЌ»я ќ“ “ј…ћ?–ј
Timer: clr w
out TCCR0B,w ; выключить таймер
pop w ; очищаем стек
pop w
rjmp Reset ; ресетимс¤;— –јЅќ„јя „ј—“№
;— ѕроверка номера системы и команды
rab_chast: clr w
out TCCR0B,w ; выключить таймер
out TCNT0,w ; сбросить таймер
pop w ; очищаем стек
pop w
clc
rol LBC ; сдвигаем всЄ, кроме номера команды в MBC
rol MBC
clc
rol LBC
rol MBC
lsr LBC ; выравниваем номер команды младшим битом к
lsr LBC ; младшему биту байта
in w,PORTB ; читаем порт B
cpi LBC,CMD_1
breq Button1
cpi LBC,CMD_2
breq Button2
cpi LBC,CMD_3
breq Button3
cpi LBC,CMD_4
breq Button4
rjmp Reset
Button1: ldi Sch,0b00000001
eor w,Sch ; инвертируем нулевой бит
out PORTB,w
rjmp Thats_all
Button2: ldi Sch,0b00000010
eor w,Sch ; инвертируем первый бит
out PORTB,w
rjmp Thats_all
Button3: ldi Sch,0b00000100
eor w,Sch ; инвертируем второй бит
out PORTB,w
rjmp Thats_all
Button4: ldi Sch,0b00010000
eor w,Sch ; инвертируем четвЄртый бит
out PORTB,w
Thats_all: rcall Pause
rjmp Reset
Pause: ldi R22, Delay ; загрузка константы для задержки в регистр R22
WLoop0:
ldi R23, 0x28 ; загружаем число 40 (0x28) в регистр R23
WLoop1:
ldi R24, 0xFF ; загружаем число 255 (0xFF) в регистр R24
WLoop2:
dec R24 ; уменьшаем значение в регистре R24 на 1
brne WLoop2 ; возврат к WLoop2 если значение в R24 не равно 0
dec R23 ; уменьшаем значение в регистре R23 на 1
brne WLoop1 ; возврат к WLoop1 если значение в R23 не равно 0
dec R22 ; уменьшаем значение в регистре R22 на 1
brne WLoop0 ; возврат к WLoop0 если значение в R22 не равно 0
eor w,Sch ; инвертируем второй бит
out PORTB,w
ret ; возврат из подпрограммы PauseЗдравствуйте. Помогите считать температуру с датчика LMT01. Датчик подключен к ножке внешнего прерывания. При попытках считать импульсы возникла проблема с таймингами между периодами импульсов и паузой.
Здравствуйте! Во-первых, большое спасибо вам за сайт!!!
Но, Изучая урок 22 часть 2. ни как не могу понять:
Ни как не могу понять как получили значение с АЦП!
return (unsigned int) ADC; как это работает?
где обработка регистров ADCH и ADCL. как в 3 части урока?
Поясните пожалуйста этот момент.Andry_EXOSpace, просто возвращаем значение 10 бит регистра ADC целиком, даташит стр.208.
Для разработки устройства на Atmega 8 необходимо задействовать ШИМ (PB1-PB3)и аппаратный SPI (PB1-PB4) но вся беда в том что они занимают одни и те же ноги
можно как то реализовать их параллельную работу или нет ?
И вообще это реализуемо ?Может по очереди их использовать? или аппаратный SPI?
Приветствую всех форумчан и автора сайта! Изучаю программирование Atmega8 на языке С. Пытаюсь передать температуру измеренную DS18B20 с помощью модуля NRF24L01, по мотивам урока 105 «NRF24L01. Передаём данные». Вот кусок программы на передающей части в основной программе:
…
int main (void){
…
while(1)
{
if (TEMPER_Transmit(buf1))
{
USART_Transmit(buf1[0]);
USART_Transmit(buf1[1]);
NRF24L01_Send(buf1);
}
_delay_ms(1000);
}
}
Тут я думаю, все нормально, USART в терминальной программе показывает два байта со значением температуры (например 8А 01), значения меняются при нагреве ds18b20.В приемной части кусок программы такой:
…
#define TX_PLOAD_WIDTH 2
uint8_t RX_BUF[TX_PLOAD_WIDTH] = {0};
…
int main(void){
…
while(1)
{
uint8_t status=0x01;
if (BitIsClear(PINC,IRQ)) //если нога IRQ упала, значит надо выяснить, может принят байт?
{
status = NRF24_ReadReg(STATUS); //прочитали статус регистр
_delay_us(10);
status = NRF24_ReadReg(STATUS);
if(status & 0x40)
{
NRF24_Read_Buf(RD_RX_PLOAD,RX_BUF,TX_PLOAD_WIDTH);Temp_L = RX_BUF[0];
Temp_H = RX_BUF[1];
USART_Transmit(Temp_L);
USART_Transmit(Temp_H);
…
…// здесь подпрограмма вывода показаний на экран
}
}
Модуль NRF24L01 работает, принимает что-то, USART на терминальной программе показывает постоянные цифры 64 65, снова 64 65 и так далее одно и тоже, значение которой не меняется при изменении температуры в передающей части. Прошу помощи, что в коде не так, как в принимающей части подправить, чтобы получить правильную информацию? -
АвторСообщения
- Для ответа в этой теме необходимо авторизоваться.