реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> SPI и Atmega128A
ADEPTPS
сообщение Dec 14 2011, 08:03
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683



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

В даташите есть функция настройки 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)));//ждем пока передача завершится
}
Go to the top of the page
 
+Quote Post
hd44780
сообщение Dec 14 2011, 08:13
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



SPI отсылает и принимает ОДНОВРЕМЕННО.
Т.е. чтобы что-то принять, мастер должен что-то отослать.

//функция передачи байта
char SPI_MasterTransmit(char cData)
{
SPDR = cData;//начинаем передачу
while(!(SPSR & (1<<SPIF)));//ждем пока передача завершится
return SPDR;
}

Вызов:
receivedByte = SPI_MasterTransmit(0xFF);


Сообщение отредактировал hd44780 - Dec 14 2011, 08:14


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
arttab
сообщение Dec 15 2011, 01:27
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 432
Регистрация: 7-12-04
Из: Новосибирск
Пользователь №: 1 371



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


--------------------
OrCAD, Altium,IAR, AVR....
Go to the top of the page
 
+Quote Post
ADEPTPS
сообщение Dec 15 2011, 07:29
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683



А как мне быть если ответом будет слово?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 15 2011, 07:43
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (arttab @ Dec 15 2011, 03:27) *
есть такое. причем когда мастер только передает и входная линия физически отсутствует все равно надо читать из регистра ресивера. на меге8535 c этим столкнулся.
Странно. На меге8 считываю только тогда, когда нужны принятые данные. И все работает. И с прерываниями, и без. Вроде бы дата рождения у них примерно одинаковая, откуда же такое отличие?


QUOTE (ADEPTPS @ Dec 15 2011, 09:29) *
А как мне быть если ответом будет слово?
Принять два байта и склеить из них двухбайтовую переменную?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
ADEPTPS
сообщение Dec 15 2011, 07:52
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683



судя по последней конструкции, один байт отдали - один приняли, а у меня один байт отдали - слово приняли
Go to the top of the page
 
+Quote Post
hd44780
сообщение Dec 15 2011, 09:09
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



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

word rWord = SPI_MasterTransmit(0xFF); /// Старший байт
rWord <<= 8;
rWord |= SPI_MasterTransmit(0xFF); // Младший

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

Сообщение отредактировал hd44780 - Dec 15 2011, 09:10


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
usav
сообщение Dec 16 2011, 12:21
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 22
Регистрация: 22-01-10
Из: Kiev
Пользователь №: 55 001



а у меня один байт отдали - слово приняли
----------------------------------------------------
SPI - синхронный интерфейс с линией СИНХРО. Данные (по ОПРЕДЕЛЕНИЮ!)
передвигаются из/в обычные сдвиговые регистры. Значит надо передать
поочередно два байта (один - пустой) и т.о. сформировать 8+8 синхроимпульсов,
по которым с другой стороны вытолкнутся к вам 8 +8 бит.
А вообще, прежде чем писать (и прогу и сюда) надо хотя бы картинки в DS посмотреть!
Go to the top of the page
 
+Quote Post
ADEPTPS
сообщение Dec 23 2011, 10:45
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683



Посмотрите кто-нибудь мой код, если не трудно, на мой взгляд проблема в настройке SPI:
это подпрограмма для инициализации и считывания данных с АЦП AD7792.
Помогите пожалуйста!

CODE
#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;
}


Цитата(usav @ Dec 16 2011, 16:21) *
А вообще, прежде чем писать (и прогу и сюда) надо хотя бы картинки в DS посмотреть!


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

Сообщение отредактировал ADEPTPS - Dec 23 2011, 09:51
Go to the top of the page
 
+Quote Post
Tolyaha
сообщение Dec 23 2011, 10:55
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 116
Регистрация: 2-03-07
Из: Украина
Пользователь №: 25 826



Цитата(ADEPTPS @ Dec 23 2011, 11:50) *
Посмотрите кто-нибудь мой код

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

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 файл с дефайнами (я думаю обязательно есть в для любой среды программирования)
Go to the top of the page
 
+Quote Post
ADEPTPS
сообщение Dec 23 2011, 11:04
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683



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

SPI завелся вроде, но на ЖКИ по прежнему 0...
Go to the top of the page
 
+Quote Post
Tolyaha
сообщение Dec 23 2011, 11:16
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 116
Регистрация: 2-03-07
Из: Украина
Пользователь №: 25 826



Цитата(ADEPTPS @ Dec 23 2011, 13:04) *
Спасибо, сейчас попробую!

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


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

#define DD_SS 0
#define DD_MOSI 2
#define DD_MISO 3
#define DD_SCK 1
Go to the top of the page
 
+Quote Post
ADEPTPS
сообщение Dec 23 2011, 11:48
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683



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

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

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

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

#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;
}


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

CODE

#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;
}

}
Go to the top of the page
 
+Quote Post
Tolyaha
сообщение Dec 23 2011, 11:59
Сообщение #14


Частый гость
**

Группа: Свой
Сообщений: 116
Регистрация: 2-03-07
Из: Украина
Пользователь №: 25 826



Давай попорядку, проверим связь и прочитаем статус регистр и сравним с 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);
Go to the top of the page
 
+Quote Post
ADEPTPS
сообщение Dec 23 2011, 12:09
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683



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

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

а сори, многовато, микросекунды нужны тогда _delay_ms(5); так получается из-за того что тактовая частота не прописана (определено экспериментальным путем)
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 01:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01497 секунд с 7
ELECTRONIX ©2004-2016