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

проблема с nrf24l01


igor_ryzhov

Рекомендуемые сообщения

Здравствуйте! Уже неделю пытаюсь запустить данный радиомодуль, но пока безуспешно. Для начала решил проверить работает ли 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)
    {		
        
    }
}

 

Изменено пользователем igor_ryzhov
Ссылка на комментарий
Поделиться на другие сайты

ну функции чтения и записи 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);

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

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

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

На тот момент я никогда не имел дела с NRF. Перебрал несколько примеров из инета, трансивер не пошел. На форуме попросил у ребят рабочий пример, на котором завелось с полпинка. Пример я причесал под себя, но особо не лез в код. Дописал нужные мне функции. Мне лень сейчас вникать. У меня все завелось и работало. Заказчик пропал, потому я отложил трансиверы до лучших времен.

По вашему коду. Например: PORTB &=~(1 << SS); Если вы не знаете приоритет использования операторов, то лучше обрамлять в скобки, иначе вы получите совсем не тот результат, на который рассчитываете. Эти места нужно проверять в дизассемблере. Лично я не надеюсь на свою память и обрамляю в скобки. PORTB &= (~(1 << SS));

 

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

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

 

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

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

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

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

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

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

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

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

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

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

Изменено пользователем igor_ryzhov
Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

SPI если SS пин будет как вход, то при низком уровне мк будет работать как слейв. притом, если в программе вы напишете PORTX, LOW, то мк будет как слейв. поэтому ss пин нужно сразу настраивать на выход. внутренней подтяжки может не хватить. достаточно ладонью рядом с мк провести, чтобы мк сошел. с ума от наводок. я всегда использую внешние резисторы на несколько кОм, до 10 кОм. 

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

я читал про пин ss что нужно подтягивать резистором к питанию, но не придал значения. Попробую так сделать, вдруг в этом дело..

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

подтянул резистором на 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

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

Только что, Yurkin2015 сказал:

  Подключать надо так:

MOSI -> MISO

MISO -> MOSI

Это кто вам такое сказал?

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

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

1 час назад, Yurkin2015 сказал:

  Подключать надо так:

MOSI -> MISO

MISO -> MOSI

Master In Slave Out, Master Out Slave In - то есть подключать нужно MISO-MISO, MOSI-MOSI

А UART Tx-Rx, Rx-Tx

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

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);

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

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

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

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

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...