Программирование МК AVR



Помечено: 

Просмотр 9 сообщений - с 46 по 54 (из 54 всего)
  • Автор
    Сообщения
  • #22271
    cedric69
    Участник

    Здравствуйте! Нужна помощь. Пробую задействовать два входа АЦП на тини13 и чтоб замеры на каждом в пине соответствовали действиям на двух соответствующих выходах. Столкнулся с проблемой — не могу сохранить значения . Значения АЦП вмешиваются во все функции дрыгая не своими ногами. Как сохранить значение предназначенное для отдельной функции и соответственно переписать именно когда дойдет очередь. Очередь я считаю по if (ADCSRA&(1<<ADSC)) и скажем если X четное то «направо» нечетное «налево» За ранее спасибо.

    #22291
    Zhenya
    Участник

    Здравствуйте! Нужна помощь по индикации, но в 3 разряда. Комментарские варинты не работают, а код ниже хорошо показывает 2 разряда.

    #22392
    oleg5672
    Участник

    Здравствуйте друзья нужна помощь подправить код ИК-приёмник на 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

    #22565
    Ilya3145456
    Участник

    Здравствуйте. Помогите считать температуру с датчика LMT01. Датчик подключен к ножке внешнего прерывания. При попытках считать импульсы возникла проблема с таймингами между периодами импульсов и паузой.

    #22577
    Andry_EXOSpace
    Участник

    Здравствуйте! Во-первых, большое спасибо вам за сайт!!!
    Но, Изучая урок 22 часть 2. ни как не могу понять:
    Ни как не могу понять как получили значение с АЦП!
    return (unsigned int) ADC; как это работает?
    где обработка регистров ADCH и ADCL. как в 3 части урока?
    Поясните пожалуйста этот момент.

    #22691
    megger380
    Участник

    Andry_EXOSpace, просто возвращаем значение 10 бит регистра ADC целиком, даташит стр.208.

    #22904
    Vlakar
    Участник

    Для разработки устройства на Atmega 8 необходимо задействовать ШИМ (PB1-PB3)и аппаратный SPI (PB1-PB4) но вся беда в том что они занимают одни и те же ноги
    можно как то реализовать их параллельную работу или нет ?
    И вообще это реализуемо ?

    #22965
    Andry_EXOSpace
    Участник

    Может по очереди их использовать? или аппаратный SPI?

    #24254
    Solder
    Участник

    Приветствую всех форумчан и автора сайта! Изучаю программирование 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 и так далее одно и тоже, значение которой не меняется при изменении температуры в передающей части. Прошу помощи, что в коде не так, как в принимающей части подправить, чтобы получить правильную информацию?

  • Автор
    Сообщения
  • #22271

    cedric69
    Участник
    • Оффлайн

    Здравствуйте! Нужна помощь. Пробую задействовать два входа АЦП на тини13 и чтоб замеры на каждом в пине соответствовали действиям на двух соответствующих выходах. Столкнулся с проблемой — не могу сохранить значения . Значения АЦП вмешиваются во все функции дрыгая не своими ногами. Как сохранить значение предназначенное для отдельной функции и соответственно переписать именно когда дойдет очередь. Очередь я считаю по if (ADCSRA&(1<<ADSC)) и скажем если X четное то «направо» нечетное «налево» За ранее спасибо.

    #22291

    Zhenya
    Участник
    • Оффлайн

    Здравствуйте! Нужна помощь по индикации, но в 3 разряда. Комментарские варинты не работают, а код ниже хорошо показывает 2 разряда.

    #22392

    oleg5672
    Участник
    • Оффлайн

    Здравствуйте друзья нужна помощь подправить код ИК-приёмник на 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

    #22565

    Ilya3145456
    Участник
    • Оффлайн

    Здравствуйте. Помогите считать температуру с датчика LMT01. Датчик подключен к ножке внешнего прерывания. При попытках считать импульсы возникла проблема с таймингами между периодами импульсов и паузой.

    #22577

    Andry_EXOSpace
    Участник
    • Оффлайн

    Здравствуйте! Во-первых, большое спасибо вам за сайт!!!
    Но, Изучая урок 22 часть 2. ни как не могу понять:
    Ни как не могу понять как получили значение с АЦП!
    return (unsigned int) ADC; как это работает?
    где обработка регистров ADCH и ADCL. как в 3 части урока?
    Поясните пожалуйста этот момент.

    #22691

    megger380
    Участник
    • Оффлайн

    Andry_EXOSpace, просто возвращаем значение 10 бит регистра ADC целиком, даташит стр.208.

    #22904

    Vlakar
    Участник
    • Оффлайн

    Для разработки устройства на Atmega 8 необходимо задействовать ШИМ (PB1-PB3)и аппаратный SPI (PB1-PB4) но вся беда в том что они занимают одни и те же ноги
    можно как то реализовать их параллельную работу или нет ?
    И вообще это реализуемо ?

    #22965

    Andry_EXOSpace
    Участник
    • Оффлайн

    Может по очереди их использовать? или аппаратный SPI?

    #24254

    Solder
    Участник
    • Оффлайн

    Приветствую всех форумчан и автора сайта! Изучаю программирование 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 и так далее одно и тоже, значение которой не меняется при изменении температуры в передающей части. Прошу помощи, что в коде не так, как в принимающей части подправить, чтобы получить правильную информацию?

Просмотр 9 сообщений - с 46 по 54 (из 54 всего)
  • Для ответа в этой теме необходимо авторизоваться.