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

igor_ryzhov

Members
  • Постов

    16
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные igor_ryzhov

  1. 26 минут назад, Sergey32 сказал:

    Спасибо, попробую. А требования к транзистору какие? Реле будет маломощное

    Если рэле маломощное, то транзистор любой маломощный п-н-п диод 1н4007 и т. п.

  2. Можно установить TCCR1B |=(1 << CS12)|(1 << CS10); // :1024;      OCR1A = 46875,  при f_clk = 8000000гц.

    Но при этом будет небольшая погрешность, так как 800000/1024 = 7812.5, либо использовать дополнительную переменную для подсчета количества переполнений таймера при меньшем делителе таймера, либо понизить тактовую частоту контроллера

     

     

  3. uint8_t spi_writeread(uint8_t data)
    {
        SPDR = data;
        while((SPSR & (1<<SPIF)) == 0);
        return SPDR;
    }
    
    uint8_t mirf_read_register(uint8_t reg)
    {
       PORTB &=~(1 << SS);
       spi_writeread(R_REGISTER | reg);
        uint8_t result = spi_writeread(NOP);
        PORTB |= (1 << SS);
        return result;
    }
    
    void mirf_write_register(uint8_t reg, uint8_t value)
    {
       PORTB &=~(1 << SS);
       spi_writeread(W_REGISTER | reg);
       spi_writeread(value);
       PORTB |= (1 << SS);
    }
    
    int main(void)
    { 
    	
    	SPCR = (1 << SPE) | (1 << MSTR); // режим 0, мастер, частота 1/4 от частоты ЦП
    	
    	DDRC |= (1<<CE);
    	DDRC &=~(1<<IRQ);
    	
    	DDRB |= (1<<SCK)|(1<<MOSI)|(1<<SS)|(1<<PB1);
    	DDRB &=~(1<<MISO);
    	PORTB |= (1<<SS);
    		
    	mirf_write_register(RF_CH, 25);
    	
    	if((mirf_read_register(RF_CH) == 25))
    	{
    		PORTB |= (1<<PB1);
    	}		
    			
        while(1)
        {		
            
        }
    }

    заработало!!! Попытаюсь найти ошибку у себя в коде

    Всем спасибо за помощь!!!)

    ошибка была здесь: вместо while (SPSR & (1 << SPIF)); нужно было написать while((SPSR & (1<<SPIF)) == 0);

  4. подтянул резистором на 220 ои, все равно не записывается регистр..

    DDRB |= (1<<SCK)|(1<<MOSI)|(1<<SS)|(1<<PB1);

    в 1 сообщении полный код со всеми настройками портов

    если написать так, то светодиод включается:

    write_register(RF_CH, 25);
        
        if(!(read_register(RF_CH) == 25))
        {
            PORTB |= (1<<PB1);
        }    

    соответственно в регистре явно не 25

  5.  

    PORTB&=~(1<<SS) - в других проектах так пишу, всегда работает

    может не правильно подключил модуль?

    подключил модуль так:

    МК---------------Радиомодуль 

    MOSI ---------->MOSI

    MISO----------->MISO

    SCK------------>sck

    ss--------------->csn

    PC0---------------се

    PC2---------------irq

  6. ну функции чтения и записи 1 байта в Вашем примере точно такие как и у меня. По прежнему не работает ничего. 

    uint8_t read_register(uint8_t address) //чтение байта из оз, address -адрес байта
    {
    	    address = address | R_REGISTER;
    	    PORTB &=~(1 << SS); //Прижимаем вывод CSN к земле, тем самым сообщаем о начале обмена данных.
    		SPDR = address;
            while (SPSR & (1 << SPIF));//ожидаем когда освободится SPI для последующей записи байта
            if (!(address == STATUS))
            {  
    			SPDR = NOP;           
    			while (SPSR & (1 << SPIF));
            }       
            PORTB |= (1 << SS);//Вывод CSN(SS) МК к питанию, обмен данных завершен.
            return SPDR;		
    }
    
    void write_register(uint8_t address, uint8_t data) //адрес регистра,что пишем в регистр.
    {
            address = address | W_REGISTER; //накладываем маску
            PORTB &=~(1 << SS);
            SPDR = address;
            while (SPSR & (1 << SPIF));
            SPDR = data;
            while (SPSR & (1 << SPIF));
            address = SPDR; //это для сброса флага SPIF
            PORTB |= (1 << SS);
    }

    Это в Вашем примере:

    u08 spi_writeread(u08 data)
    {
        SPDR = data;
        while((SPSR & (1<<SPIF)) == 0);
        return SPDR;
    }
    
    u08 mirf_read_register(u08 reg) // чтение 1 байта
    {
       mirf_CSN_lo;
       spi_writeread(R_REGISTER | (REGISTER_MASK & reg));
        u08 result = spi_writeread(NOP);
        mirf_CSN_hi;
        return result;
    }
    
    void mirf_write_register(u08 reg, u08 value) // запись 1 байта
    {
       mirf_CSN_lo;
       spi_writeread(W_REGISTER | (REGISTER_MASK & reg));
       spi_writeread(value);
       mirf_CSN_hi;
    }

    единственно не пойму, для чего в этой строчке REGISTER_MASK

    spi_writeread(W_REGISTER | (REGISTER_MASK & reg));

     если можно написать  так:

    spi_writeread(W_REGISTER | reg);

    Или так нельзя? 

  7. Здравствуйте! Уже неделю пытаюсь запустить данный радиомодуль, но пока безуспешно. Для начала решил проверить работает ли SPI. Контроллер атмега8. Проблема заключается в том, что я не могу записать регистр в нрф, то есть я записываю туда какое - то значение, в пределах допустимого, например в регистр RF_CH записываю 25, затем считываю этот регистр и если там хранится 25, то должен загореться светодиод, но фиг там.. Пробовал тоже самое с регистром STATUS, та же беда... В чем может быть проблема? Запись и чтение реализовано с помощью функций write_register и read_register соответственно. Светодиод висит на PB1

    #define F_CPU 1000000UL
    
    #include <avr/io.h>
    #include <util/delay.h>
    
    
    #define CE  PC0
    #define IRQ PC2
    
    #define MOSI PB3
    #define MISO PB4
    #define SCK PB5
    #define SS PB2 
    
    #define R_REGISTER          0x00 // + n Прочитать регистр n
    #define W_REGISTER          0x20 // + n Записать регистр n
    #define R_RX_PAYLOAD        0x61 // Принять данные данные из верхнего слота очереди приёмника. После чтения, данные из очереди удаляются
    #define W_TX_PAYLOAD        0xA0 // Записать в очередь передатчика данные для отправки
    #define FLUSH_TX            0xE1 // Сбросить очередь передатчика
    #define FLUSH_RX            0xE2 // Сбросить очередь приёмника
    #define REUSE_TX_PL         0xE3 // Использовать повторно последний переданный пакет
    #define R_RX_PL_WID         0x60 // Прочитать размер данных принятого пакета в начале очереди приёмника. Значение больше 32, означает ошибку приёма, пакет должен быть удалён командой FLUSH_RX
    #define W_ACK_PAYLOAD       0xA8 // + p Записать данные для отправки с пакетом подтверждения по каналу p. При этом бит EN_ACK_PAY в регистре FEATURE должен быть установлен
    #define W_TX_PAYLOAD_NOACK  0xB0 // Записать в очередь передатчика данные для отправки, для которых не требуется подтверждение приёма.
    #define NOP                 0xFF // Нет операции. Может быть использовано для чтения регистра статуса
    
    /* Регистры */
    
    #define CONFIG      0x00 // Регистр настроек
    #define EN_AA       0x01 // Выбор автоподтверждения
    #define EN_RXADDR   0x02 // Выбор каналов приёмника
    #define SETUP_AW    0x03 // Настройка размера адреса
    #define SETUP_RETR  0x04 // Настройка повторной отправки
    #define RF_CH       0x05 // Номер радиоканала, на котором осуществляется работа. От 0 до 125. Несущая частота равна 2400 + номер_канала МГц
    #define RF_SETUP    0x06 // Настройка радиоканала
    #define STATUS      0x07 // Регистр статуса. Значение регистра статуса также передаётся к МК по SPI, одновременно с передачей от МК байта команды
    #define OBSERVE_TX  0x08 // Количество повторов передачи и потерянных пакетов
    #define RPD         0x09 // Мощность принимаемого сигнала. Если младший бит = 1, то уровень сигнала более -64dBm 
    #define RX_ADDR_P0  0x0A // 3-5 байт (начиная с младшего байта). Адрес канала 0 приёмника. При использовании в режиме передатчика, этот адрес должен быть равен TX_ADDR, для использования автоподтверждения приёма
    #define RX_ADDR_P1  0x0B // 3-5 байт (начиная с младшего байта). Адрес канала 1 приёмника, одновременно задаёт старшие байты адресов каналов 2 - 5.
    #define RX_ADDR_P2  0x0C // Младший байт адреса канала 2 приёмника. Старшие байты соответствуют значению старших байт в регистре RX_ADDR_P1
    #define RX_ADDR_P3  0x0D // Младший байт адреса канала 3 приёмника. Старшие байты соответствуют значению старших байт в регистре RX_ADDR_P1
    #define RX_ADDR_P4  0x0E // Младший байт адреса канала 4 приёмника. Старшие байты соответствуют значению старших байт в регистре RX_ADDR_P1
    #define RX_ADDR_P5  0x0F // Младший байт адреса канала 5 приёмника. Старшие байты соответствуют значению старших байт в регистре RX_ADDR_P1
    #define TX_ADDR     0x10 // 3-5 байт (начиная с младшего байта). Адрес устройства, которому осуществляется передача
    #define RX_PW_P0    0x11 // Размер данных при приёме по каналу 0: от 1 до 32. 0 - канал не используется.
    #define RX_PW_P1    0x12 // Размер данных при приёме по каналу 1: от 1 до 32. 0 - канал не используется.
    #define RX_PW_P2    0x13 // Размер данных при приёме по каналу 2: от 1 до 32. 0 - канал не используется.
    #define RX_PW_P3    0x14 // Размер данных при приёме по каналу 3: от 1 до 32. 0 - канал не используется.
    #define RX_PW_P4    0x15 // Размер данных при приёме по каналу 4: от 1 до 32. 0 - канал не используется.
    #define RX_PW_P5    0x16 // Размер данных при приёме по каналу 5: от 1 до 32. 0 - канал не используется.
    #define FIFO_STATUS 0x17 // Состояние очередей FIFO приёмника и передатчика
    #define DYNPD       0x1C // Выбор каналов приёмника для которых используется режим произвольной длины пакетов.
    #define FEATURE     0x1D // Регистр опций
    
    
    /* Биты регистров */
    
    // CONFIG
    #define MASK_RX_DR  6 // Запрещает прерывание по RX_DR (получение пакета)
    #define MASK_TX_DS  5 // Запрещает прерывание по TX_DS (завершение отправки пакета) 
    #define MASK_MAX_RT 4 // Запрещает прерывание по MAX_RT (превышение числа повторных попыток отправки) 
    #define EN_CRC      3 // Включает CRC
    #define CRCO        2 // Размер поля CRC: 0 - 1 байт; 1 - 2 байта
    #define PWR_UP      1 // Включение питания
    #define PRIM_RX     0 // Выбор режима: 0 - PTX (передатчик) 1 - PRX (приёмник)
    
    // EN_AA
    #define ENAA_P5 5 // Включает автоподтверждение данных, полученных по каналу 5
    #define ENAA_P4 4 // Включает автоподтверждение данных, полученных по каналу 4
    #define ENAA_P3 3 // Включает автоподтверждение данных, полученных по каналу 3
    #define ENAA_P2 2 // Включает автоподтверждение данных, полученных по каналу 2
    #define ENAA_P1 1 // Включает автоподтверждение данных, полученных по каналу 1
    #define ENAA_P0 0 // Включает автоподтверждение данных, полученных по каналу 0
    
    // EN_RXADDR
    #define ERX_P5 5 // Включает канал 5 приёмника
    #define ERX_P4 4 // Включает канал 4 приёмника 
    #define ERX_P3 3 // Включает канал 3 приёмника 
    #define ERX_P2 2 // Включает канал 2 приёмника 
    #define ERX_P1 1 // Включает канал 1 приёмника 
    #define ERX_P0 0 // Включает канал 0 приёмника 
    
    // SETUP_AW
    #define AW 0 // Два бита, Выбирает ширину поля адреса: 1 - 3 байта; 2 - 4 байта; 3 - 5 байт. 0 - недопустимое значение
    
    #define SETUP_AW_3BYTES_ADDRESS (1 << AW)
    #define SETUP_AW_4BYTES_ADDRESS (2 << AW)
    #define SETUP_AW_5BYTES_ADDRESS (3 << AW)
    
    // SETUP_RETR 
    #define ARD 4 // 4 бита. Задаёт значение задержки перед повторной отправкой пакета, 0 - 250мкс, 1 - 500мкс, 2 - 750мкс, ..., 15 - 4000мкс
    #define ARC 0 // 4 битай. Количество повторных попыток отправки. 0 - отключено, 1 - до 1 попытки, ..., 15 - до 15 попыток
    
    #define SETUP_RETR_DELAY_250MKS  (0 << ARD)
    #define SETUP_RETR_DELAY_500MKS  (1 << ARD)
    #define SETUP_RETR_DELAY_750MKS  (2 << ARD)
    #define SETUP_RETR_DELAY_1000MKS (3 << ARD)
    #define SETUP_RETR_DELAY_1250MKS (4 << ARD)
    #define SETUP_RETR_DELAY_1500MKS (5 << ARD)
    #define SETUP_RETR_DELAY_1750MKS (6 << ARD)
    #define SETUP_RETR_DELAY_2000MKS (7 << ARD)
    #define SETUP_RETR_DELAY_2250MKS (8 << ARD)
    #define SETUP_RETR_DELAY_2500MKS (9 << ARD)
    #define SETUP_RETR_DELAY_2750MKS (10 << ARD)
    #define SETUP_RETR_DELAY_3000MKS (11 << ARD)
    #define SETUP_RETR_DELAY_3250MKS (12 << ARD)
    #define SETUP_RETR_DELAY_3500MKS (13 << ARD)
    #define SETUP_RETR_DELAY_3750MKS (14 << ARD)
    #define SETUP_RETR_DELAY_4000MKS (15 << ARD)
    
    #define SETUP_RETR_NO_RETRANSMIT (0 << ARC)
    #define SETUP_RETR_UP_TO_1_RETRANSMIT (1 << ARC)
    #define SETUP_RETR_UP_TO_2_RETRANSMIT (2 << ARC)
    #define SETUP_RETR_UP_TO_3_RETRANSMIT (3 << ARC)
    #define SETUP_RETR_UP_TO_4_RETRANSMIT (4 << ARC)
    #define SETUP_RETR_UP_TO_5_RETRANSMIT (5 << ARC)
    #define SETUP_RETR_UP_TO_6_RETRANSMIT (6 << ARC)
    #define SETUP_RETR_UP_TO_7_RETRANSMIT (7 << ARC)
    #define SETUP_RETR_UP_TO_8_RETRANSMIT (8 << ARC)
    #define SETUP_RETR_UP_TO_9_RETRANSMIT (9 << ARC)
    #define SETUP_RETR_UP_TO_10_RETRANSMIT (10 << ARC)
    #define SETUP_RETR_UP_TO_11_RETRANSMIT (11 << ARC)
    #define SETUP_RETR_UP_TO_12_RETRANSMIT (12 << ARC)
    #define SETUP_RETR_UP_TO_13_RETRANSMIT (13 << ARC)
    #define SETUP_RETR_UP_TO_14_RETRANSMIT (14 << ARC)
    #define SETUP_RETR_UP_TO_15_RETRANSMIT (15 << ARC)
    
    // RF_SETUP
    #define CONT_WAVE   7 // (Только для nRF24L01+) Непрерывная передача несущей (для тестов)
    #define RF_DR_LOW   5 // (Только для nRF24L01+) Включает низкую скорость передачи 250кбит/с. При этом бит RF_DR_HIGH должен быть 0
    #define PLL_LOCK    4 // Для тестов
    #define RF_DR_HIGH  3 // Выбор скорости обмена (при значении бита RF_DR_LOW = 0): 0 - 1Мбит/с; 1 - 2Мбит/с
    #define RF_PWR      1 // 2бита. Выбирает мощность передатчика: 0 - -18dBm; 1 - -16dBm; 2 - -6dBm; 3 - 0dBm
    
    #define RF_SETUP_MINUS18DBM (0 << RF_PWR)
    #define RF_SETUP_MINUS12DBM (1 << RF_PWR)
    #define RF_SETUP_MINUS6DBM  (2 << RF_PWR)
    #define RF_SETUP_0DBM       (3 << RF_PWR)
    
    #define RF_SETUP_1MBPS (0 << RF_DR_HIGH)
    #define RF_SETUP_2MBPS (1 << RF_DR_HIGH)
    #define RF_SETUP_250KBPS (1 << RF_DR_LOW) // этот режим не должен использоваться с автоматическим контролем отправки
    
    // STATUS
    #define RX_DR   6 // Флаг получения новых данных в FIFO приёмника. Для сброса флага нужно записать регистр со значением этого бита 1
    #define TX_DS   5 // Флаг завершения передачи. Для сброса флага нужно записать регистр со значением этого бита 1
    #define MAX_RT  4 // Флаг превышения установленного числа повторов. Без сброса этого флага дальнейший радиообмен не возможен. Для сброса флага нужно записать регистр со значением этого бита 1. Передаваемые данные остаются в очереди, их можно удалить командой FLUSH_TX
    #define RX_P_NO 1 // 3 бита. Номер канала, данные для которого доступны в FIFO приёмника: 0 - канал 0, ..., 5 - канал 5, 7 - FIFO приёмника пусто.
    #define TX_FULL_STATUS 0 // Признак заполнения FIFO передатчика: 1 - FIFO передатчика заполнено; 0 - есть доступные слоты (переименовано из TX_FULL во избежание путаницы с одноимённым битом из регистра FIFO_STATUS)
    
    // OBSERVE_TX
    #define PLOS_CNT  4 // 4 бита. Общее количество пакетов без подтверждения. Не меняется после достижения 15. Сбрасывается записью регистра RF_CH
    #define ARC_CNT   0 // 4 бита. Количество предпринятых повторов при последней отправке. Сбрасывается при начале отправки следующего пакета
    
    // FIFO_STATUS
    #define TX_REUSE      6 // Признак готовности последнего пакета для повтрной отправке. Устанавливается командой REUSE_TX_PL
    #define TX_FULL_FIFO  5 // Флаг переполнения FIFO очереди передатчика: 0 - есть свободное место в очереди; 1 - очередь переполнена (переименовано из TX_FULL во избежание путаницы с одноимённым битом из регистра STATUS)
    #define TX_EMPTY      4 // Флаг освобождения FIFO очереди передатчика: 0 - в очереди есть данные; 1 - очередь пуста
    #define RX_FULL       1 // Флаг переполнения FIFO очереди приёмника: 0 - есть свободное место в очереди; 1 - очередь переполнена
    #define RX_EMPTY      0 // Флаг освобождения FIFO очереди приёмника: 0 - в очереди есть данные; 1 - очередь пуста
    
    // DYNDP
    #define DPL_P5 5 // Включает приём пакетов произвольной длины по каналу 5 (должы быть установлены биты EN_DPL в регистры FEATURE и ENAA_P5 в регистре EN_AA)
    #define DPL_P4 4 // Включает приём пакетов произвольной длины по каналу 4 (должы быть установлены биты EN_DPL в регистры FEATURE и ENAA_P4 в регистре EN_AA)
    #define DPL_P3 3 // Включает приём пакетов произвольной длины по каналу 3 (должы быть установлены биты EN_DPL в регистры FEATURE и ENAA_P3 в регистре EN_AA)
    #define DPL_P2 2 // Включает приём пакетов произвольной длины по каналу 2 (должы быть установлены биты EN_DPL в регистры FEATURE и ENAA_P2 в регистре EN_AA)
    #define DPL_P1 1 // Включает приём пакетов произвольной длины по каналу 1 (должы быть установлены биты EN_DPL в регистры FEATURE и ENAA_P1 в регистре EN_AA)
    #define DPL_P0 0 // Включает приём пакетов произвольной длины по каналу 0 (должы быть установлены биты EN_DPL в регистры FEATURE и ENAA_P0 в регистре EN_AA)
    
    // FEATURE  
    #define EN_DPL      2 // Включает поддержку приёма и передачи пакетов произвольной длины
    #define EN_ACK_PAY  1 // Разрешает передачу данных с пакетами подтверждения приёма
    #define EN_DYN_ACK  0 // Разрешает использование W_TX_PAYLOAD_NOACK
    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    //uint8_t mas[5];
    //uint8_t dataOnTheModule[5] = { 254, 254, 254, 254, 254};
    	
    uint8_t read_register(uint8_t address) //чтение байта из оз, address -адрес байта
    {
    	    address = address | R_REGISTER;
    	    PORTB &=~(1 << SS); //Прижимаем вывод CSN к земле, тем самым сообщаем о начале обмена данных.
    		SPDR = address;
            while (SPSR & (1 << SPIF));//ожидаем когда освободится SPI для последующей записи байта
            if (!(address == STATUS))
            {  
    			SPDR = NOP;           
    			while (SPSR & (1 << SPIF));
            }       
            PORTB |= (1 << SS);//Вывод CSN(SS) МК к питанию, обмен данных завершен.
            return SPDR;		
    }
    
    void write_register(uint8_t address, uint8_t data) //адрес регистра,что пишем в регистр.
    {
            address = address | W_REGISTER; //накладываем маску
            PORTB &=~(1 << SS);
            SPDR = address;
            while (SPSR & (1 << SPIF));
            SPDR = data;
            while (SPSR & (1 << SPIF));
            address = SPDR; //это для сброса флага SPIF
            PORTB |= (1 << SS);
    }
    
    //void read_several_registers(uint8_t address, uint8_t *buff, uint8_t size_reg) //чтение мнoгобайтового регистра, address - адрес байта
    {
    	    address = address | W_REGISTER;
            PORTB &=~(1 << SS); //Прижимаем вывод CSN к земле, тем самым сообщаем о начале обмена данных.
            SPDR = address;
            while (SPSR & (1 << SPIF));//ожидаем когда освободится SPI для последующей записи байта
            while(size_reg--)
    		{
    		   SPDR = NOP;
               while (SPSR & (1 << SPIF));
    		   *buff = SPDR;
    		   *buff++;
    		}	
    	    address = SPDR;       //для сброса флага SPIF		
    	    PORTB |= (1 << SS);//Вывод CSN(SS) МК к питанию, обмен данных завершен.
    }
    
    //void write_several_registers(uint8_t address, uint8_t *data, uint8_t size_reg)//адрес регистра, что пишем в регистр, размер регистра в байтах
    {
    	    address = address | W_REGISTER; //накладываем маску и отправляем адрес, в который хотим записать
            PORTB &=~(1 << SS);
    		SPDR = address;
    		while (SPSR & (1 << SPIF));		
    		while(size_reg--)
    		{		
               SPDR = *data;
               while (SPSR & (1 << SPIF));
    		   *data++;		
    		}				
            address = SPDR; //это для сброса флага SPIF		
            PORTB |= (1 << SS);
    }
    
    //char writebyte(unsigned char cData)
    {
    	SPDR = cData;
    	while(!(SPSR & (1<<SPIF)));
    	return SPDR;
    }
    
    //uint8_t readreg (uint8_t reg)
    {
    	_delay_us(10);
    	PORTB &=~(1 << SS);
    	_delay_us(10);
    	writebyte(R_REGISTER+reg);
    	_delay_us(10);
    	reg = writebyte(NOP);
    	_delay_us(10);
    	PORTB |= (1 << SS);
    	return reg;
    }
    
    int main(void)
    { 
    	
    	SPCR = (1 << SPE) | (1 << MSTR); // режим 0, мастер, частота 1/4 от частоты ЦП
    	
    	DDRC |= (1<<CE);
    	DDRC &=~(1<<IRQ);
    	
    	DDRB |= (1<<SCK)|(1<<MOSI)|(1<<SS)|(1<<PB1);
    	DDRB &=~(1<<MISO);
    	PORTB |= (1<<SS);
    		
    	write_register(RF_CH, 25);
    	
    	if(read_register(RF_CH) == 25)
    	{
    		PORTB |= (1<<PB1);
    	}		
    			
        while(1)
        {		
            
        }
    }

     

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