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

Проблема:

не получается принять данные.

 

В даташите есть функция настройки SPI на мастер: // в ней есль только отправка данных, пытаюсь принимать данные с SPDR, но считываю лишь то что отсылаю!

 

void SPI_MasterInit()
{
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);//настраиваем на выход
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);//вкл SPI, ведущий, частота fck/16
}
//функция передачи байта
void SPI_MasterTransmit(char cData)
{
SPDR = cData;//начинаем передачу
while(!(SPSR & (1<<SPIF)));//ждем пока передача завершится
}

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


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

SPI отсылает и принимает ОДНОВРЕМЕННО.

Т.е. чтобы что-то принять, мастер должен что-то отослать.

 

//функция передачи байта

char SPI_MasterTransmit(char cData)

{

SPDR = cData;//начинаем передачу

while(!(SPSR & (1<<SPIF)));//ждем пока передача завершится

return SPDR;

}

 

Вызов:

receivedByte = SPI_MasterTransmit(0xFF);

 

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

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


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

есть такое. причем когда мастер только передает и входная линия физически отсутствует все равно надо читать из регистра ресивера. на меге8535 c этим столкнулся.

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


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

есть такое. причем когда мастер только передает и входная линия физически отсутствует все равно надо читать из регистра ресивера. на меге8535 c этим столкнулся.
Странно. На меге8 считываю только тогда, когда нужны принятые данные. И все работает. И с прерываниями, и без. Вроде бы дата рождения у них примерно одинаковая, откуда же такое отличие?

 

 

А как мне быть если ответом будет слово?
Принять два байта и склеить из них двухбайтовую переменную?

 

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


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

судя по последней конструкции, один байт отдали - один приняли, а у меня один байт отдали - слово приняли

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


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

SPI всегда и везде принимает только байты. По крайней мере, в AVR-ах.

Если надо слово, то:

 

word rWord = SPI_MasterTransmit(0xFF); /// Старший байт

rWord <<= 8;

rWord |= SPI_MasterTransmit(0xFF); // Младший

 

Если наоборот - сами напишете.

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

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


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

а у меня один байт отдали - слово приняли

----------------------------------------------------

SPI - синхронный интерфейс с линией СИНХРО. Данные (по ОПРЕДЕЛЕНИЮ!)

передвигаются из/в обычные сдвиговые регистры. Значит надо передать

поочередно два байта (один - пустой) и т.о. сформировать 8+8 синхроимпульсов,

по которым с другой стороны вытолкнутся к вам 8 +8 бит.

А вообще, прежде чем писать (и прогу и сюда) надо хотя бы картинки в DS посмотреть!

 

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


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

Посмотрите кто-нибудь мой код, если не трудно, на мой взгляд проблема в настройке SPI:

это подпрограмма для инициализации и считывания данных с АЦП AD7792.

Помогите пожалуйста!

 

#include <avr/io.h>
#include <avr/delay.h>
#include <string.h>
#include <avr/sfr_defs.h>
void spi_in(void)
{
#define DDR_SPI DDRB
#define DD_SS 0
#define DD_MOSI 2
#define DD_MISO 3
#define DD_SCK 1
#define SPE 6
#define MSTR 4
#define SPR0 0
#define SPIF 7	
PORTB |= (1<<DD_SCK)|(1<<DD_MOSI)|(1<<DD_MISO);
DDR_SPI |= (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_MISO);
DDR_SPI &= ~(1<<DD_MISO);
//SPSR |= (1<<SPI2X);
SPCR |=  (1<<SPE)|(1<<MSTR);  
}

uint8_t spi_rw(uint8_t Data)
{
SPDR = Data;//начинаем передачу
while((SPSR & (1<<SPIF)) == 0);//ждем пока передача завершится
Data = SPDR;
return Data;
}	

//Инициализация АЦП
void ad7793_init(void)
{
int8_t i;
spi_in();
for (i = 0; i < 4;i++) spi_rw(0xFF);
/* настройка АЦП */
spi_rw(0b00010000);
spi_rw(0b00010000);
spi_rw(0b00000000);
spi_rw(0b00101000);
spi_rw(0b00000000);
/* Калибровка */
spi_rw(0b00001000);
spi_rw(0b11000000);
spi_rw(0b10000001);
_delay_ms(10);
loop_until_bit_is_clear(PORTB,DD_MISO);
spi_rw(0b00001000);
spi_rw(0b10100000);
spi_rw(0b10000001);
_delay_ms(10);
loop_until_bit_is_clear(PORTB,DD_MISO);
}

//Установка режима работы
void ad7793_mode_set(unsigned char mode)
{
spi_rw(0b00001000);
if (mode == 0)
{
	spi_rw(0b00000000);
}
else spi_rw(0b00100000);
spi_rw(0b10000001);
}

uint16_t ad7793_data_get(void)
{
uint16_t t = 0;
loop_until_bit_is_clear(PORTB,DD_MISO);
spi_rw(0x58);
*((uint8_t *)(&t) + 1) = spi_rw(0xFF);
*((uint8_t *)(&t)) = spi_rw(0xFF);
return t;
}

 

А вообще, прежде чем писать (и прогу и сюда) надо хотя бы картинки в DS посмотреть!

 

Их я уже насмотрелся....

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

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


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

Посмотрите кто-нибудь мой код

То что я увидел - нужно обратить внимание на сигнал SS (слейв селект PB4) он переключает режим из мастера в слейв низким уровнем на пине, если настроен как вход, если не собираетесь переключаться, то он не должен быть входом (ниже я настроил его выходом), и для этого АЦП, если вы подключаете SCK без инвертирования я поменял фазу и полярность. Попробуйте скорректированное мной (правда смотрел по быстрому, мог ошибиться проверте по даташиту:

void spi_in(void)
{
#define DDR_SPI DDRB
#define DD_SS 0
#define DD_MOSI 2
#define DD_MISO 3
#define DD_SCK 1
             #define CPOL 3	
             #define CPHA 2	
#define SPE 6
#define MSTR 4
#define SPR0 0
#define SPIF 7	
PORTB |= (1<<DD_SCK)|(1<<DD_MOSI)|(1<<DD_MISO);
DDR_SPI |= (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
DDR_SPI &= ~(1<<DD_MISO);
//SPSR |= (1<<SPI2X);
SPCR |=  (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA);  
}


 

 

P.S. А вобще в аврстудии есть инклюдник, описывающий все биты (m8535def.inc) или еще где можно найти и h файл с дефайнами (я думаю обязательно есть в для любой среды программирования)

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


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

Спасибо, сейчас попробую!

 

SPI завелся вроде, но на ЖКИ по прежнему 0...

 

Прошу прощения пошибся просто по тексту увидел Mega8535, а нада 128, тогда оставте это по старому, а остальное попробуйте

       #define DD_SS 0
#define DD_MOSI 2
#define DD_MISO 3
#define DD_SCK 1

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


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

читается какая-то константа.... 12336 которая не зависит от входа на АЦП. но все равно большое спасибо!

 

вот немного поменял, выход с АЦП FFFF

 

Выкладываю обновленный код(без подпрограммы инициализации и вывода ЖКИ - он работает):

 

Подпрограмма АЦП:

#include <avr/io.h>
#include <avr/delay.h>
#include <string.h>
#include <avr/sfr_defs.h>

void spi_in(void)
{
#define DDR_SPI DDRB

             #define CPOL 3	
             #define CPHA 2	
#define SPE 6
#define MSTR 4
#define SPR0 0
#define SPIF 7	
 #define DD_SS 0
#define DD_MOSI 2
#define DD_MISO 3
#define DD_SCK 1
PORTB |= (1<<DD_SCK)|(1<<DD_MOSI)|(1<<DD_MISO);
DDR_SPI |= (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
DDR_SPI &= ~(1<<DD_MISO);
//SPSR |= (1<<SPI2X);
SPCR |=  (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA);  
}

uint8_t spi_rw(uint8_t Data)
{
SPDR = Data;//начинаем передачу
while((SPSR & (1<<SPIF)) == 0);//ждем пока передача завершится
Data = SPDR;
return Data;
}	

//Инициализация АЦП
void ad7793_init(void)
{
int8_t i;
spi_in();
for (i = 0; i < 4;i++) spi_rw(0xFF);
   /* настройка АЦП */
   spi_rw(0b00010000);
   spi_rw(0b00010000);
   spi_rw(0b00000000);
   spi_rw(0b00101000);
   spi_rw(0b00000000);
   /* Калибровка */
   spi_rw(0b00001000);
   spi_rw(0b11000000);
   spi_rw(0b10000001);
   _delay_ms(10);
   loop_until_bit_is_clear(DDR_SPI,DD_MISO);
   spi_rw(0b00001000);
   spi_rw(0b10100000);
   spi_rw(0b10000001);
   _delay_ms(10);
   loop_until_bit_is_clear(DDR_SPI,DD_MISO);
}

//Установка режима работы
void ad7793_mode_set(unsigned char mode)
{
   spi_rw(0b00001000);
if (mode == 0)
   {
	spi_rw(0b00000000);
   }
else spi_rw(0b00100000);
   spi_rw(0b10000001);
}

uint16_t t;

uint16_t ad7793_data_get(void)
{
t = 0;
loop_until_bit_is_clear(DDR_SPI,DD_MISO);
spi_rw(0x58);
t = (uint16_t)(spi_rw(0xFF) << 8);
t |= spi_rw(0xFF);
return t;
}

 

Главная программа:

 

#include <avr/io.h>
#include <avr/delay.h>
#include "lcd.h"
#include <stdio.h>
#include "adc2.c"


void main(void)
{
   char text[6];
unsigned int n=0;
double adc;
lcd_init();
lcd_write("Autorising...");
ad7793_init();
DDRD = (1 << 4);
ad7793_mode_set(0);
seconds(1);
lcd_init();
lcd_write("Autorising...");
seconds(1);

while (1)
{
	adc = ad7793_data_get();
	seconds(1);
	dtostrf(adc,6,0,text);
	lcd_send(COMMAND, LCD_CLEAR);
	DDRD = (1 << 4);
	lcd_write(text);
	DDRD = 0x00;
}

}

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


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

Давай попорядку, проверим связь и прочитаем статус регистр и сравним с Power-On/Reset = 0x80 (AD7792)/0x88 (AD7793)

 

 

 

И просле сброса четырех 0xFF нада выдержать паузу необходимую для сброса 500мкс

    for (i = 0; i < 4;i++) spi_rw(0xFF);
     _delay_ms(1);
   /* настройка АЦП */
    spi_rw(0b00010000);
    spi_rw(0b00010000);
    spi_rw(0b00000000);
    spi_rw(0b00101000);
    spi_rw(0b00000000);

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


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

у меня это получается _delay_ms(5000); = 500 мс

 

единички на месте)

 

а сори, многовато, микросекунды нужны тогда _delay_ms(5); так получается из-за того что тактовая частота не прописана (определено экспериментальным путем)

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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