Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SPI и Atmega128A
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
ADEPTPS
Проблема:
не получается принять данные.

В даташите есть функция настройки 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)));//ждем пока передача завершится
}
hd44780
SPI отсылает и принимает ОДНОВРЕМЕННО.
Т.е. чтобы что-то принять, мастер должен что-то отослать.

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

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


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

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

Если наоборот - сами напишете.
usav
а у меня один байт отдали - слово приняли
----------------------------------------------------
SPI - синхронный интерфейс с линией СИНХРО. Данные (по ОПРЕДЕЛЕНИЮ!)
передвигаются из/в обычные сдвиговые регистры. Значит надо передать
поочередно два байта (один - пустой) и т.о. сформировать 8+8 синхроимпульсов,
по которым с другой стороны вытолкнутся к вам 8 +8 бит.
А вообще, прежде чем писать (и прогу и сюда) надо хотя бы картинки в DS посмотреть!
ADEPTPS
Посмотрите кто-нибудь мой код, если не трудно, на мой взгляд проблема в настройке 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 посмотреть!


Их я уже насмотрелся....
Tolyaha
Цитата(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 файл с дефайнами (я думаю обязательно есть в для любой среды программирования)
ADEPTPS
Спасибо, сейчас попробую!

SPI завелся вроде, но на ЖКИ по прежнему 0...
Tolyaha
Цитата(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
ADEPTPS
читается какая-то константа.... 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;
}

}
Tolyaha
Давай попорядку, проверим связь и прочитаем статус регистр и сравним с 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);
ADEPTPS
у меня это получается _delay_ms(5000); = 500 мс

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

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

CODE

for (i = 0; i < 4;i++) spi_rw(0xFF);
_delay_ms(10);
/*проверкка связи с АЦП */
spi_rw(0x40);//настройка АЦП для чтения STATUS регистра
spi_rw(0xFF);//должно прочитаться 0x80 (AD7792)/0x88 (AD7793)


ADEPTPS
FF читает... значит связи нет(
Tolyaha
Цитата(ADEPTPS @ Dec 23 2011, 14:35) *
FF читает... значит связи нет(

а осцыла нету? проверь хоть проц, когда закорачиваеш MISO (вход SPI) на общий должно вместо 0xFF читать 0x00
ADEPTPS
рабочий день заканчивается, буду завтра уже дальше разбираться... Спасибо!

цифровой осциллограф есть, но уже выходные...
ADEPTPS
И я снова здесь! Перекорачиваю MISO на общий, ноль появляется!

- Осцилограф показал, что НА MOSI, MISO и CLK висит постоянная "1". т.е. 5 В
Палыч
АЦП имеет ногу Chip Select (CS), которой нужно "дрыгать" в определенные моменты... Что-то подобного я у Вас не нахожу... Плохо смотрел?
ADEPTPS
да, Вы правы, а когда нужно "дрыгать"?
hd44780
Цитата(ADEPTPS @ Dec 26 2011, 09:54) *
НА MOSI, MISO и CLK висит постоянная "1". т.е. 5 В


На CLK (выход синхронизации) мастера (вашей Mega128) при передаче ВСЕГДА должны быть импульсы. Вне зависимоси от того, что вы передаёте - хоть нули, хоть что.

Если их нету, 2 варианта:
1. Неправильно сконфигурировали SPI.
2. "Неправильный" контроллер - брак, сгорел SPI и т.п.

Хотя, если бы он сгорел, то он наверняка бы и не прошивался ....

Цитата(ADEPTPS @ Dec 26 2011, 10:20) *
когда нужно "дрыгать"?


1. CS=0 (м.б. 1 - уточите в ДШ на ваш АЦП).
2. Любой обмен данными
3. CS=1 (или 0).

Иначе АЦП просто пропустит ваши команди и всё остальное мимо ушей biggrin.gif .
Палыч
Цитата(ADEPTPS @ Dec 26 2011, 12:20) *
когда нужно "дрыгать"?

Установили СS в низкий - передали/прочитали нужное число байт для записи/чтения в регистр - поставили CS в высокий уровень.
Исключение можно сделать только для режима Continuous Read, ну ещё можно и для режима Continuous Conversion (для последнего - можно, но не обязательно). В этих режимах: CS - низкий в начале режима, по окончанию режима - высокий уровень.
Всё это описано/нарисовано в DS.
ADEPTPS
Спасибо, сейчас попробую!
Tolyaha
Ноль на CS обязательно, если АЦП рабочий, то на выходе данных (17 вывод) будет видна частота около 4 Hz (готовность данных). По умолчанию АЦП работает циклически с частотой 4Hz.

Вобще, если работаеш только с одним АЦП по этим линиям связи, то можно CS навсегда запаять на ноль.
ADEPTPS
SPI все же не работает, поскольку на CLK весит 5В ("еденичка"), вот что было последнее по настройке SPI (то что используется сейчас):

CODE

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;
}
Tolyaha
А как же это?

Цитата(ADEPTPS @ Dec 26 2011, 09:54) *
И я снова здесь! Перекорачиваю MISO на общий, ноль появляется!


Может не заметили в осциллограф?
ADEPTPS
Цитата(Tolyaha @ Dec 26 2011, 15:53) *
А как же это?



Может не заметили в осциллограф?


Но сигнал тактирования (CLK) то отсутствует....

еще раз проверил на осциллографе
Tolyaha
Цитата(ADEPTPS @ Dec 28 2011, 11:00) *
Но сигнал тактирования (CLK) то отсутствует....

Если точно SCK отсутствует (а не осцил неправильно настроен), то вариантов 2:
- или Вы в программе кроме показанного участка порты перенастраиваете;
- или пин у контроллера не работает.
Если SPI чувствует FF или 00 ( при закорачивании) значит он включен и вход MISO работает.
Проверте осцилом порты SCK и MOSI (PB1, PB2) настраивая их на вывод 0 (может залепуха или пробой пина).

ADEPTPS
CLK поймал:
1. я снимал показания раз в секунду
2. после перенастройки на постоянное считывание, частота CLK ~ 2МГц.

Судя по далашиту АЦП, CLK дложен быть ~ 64 кГц

Перенастраиваю SPI...

- Получил CLK ~60кГЦ
- По MOSI тоже что-то передаю
- На MISO - постоянно 5В!!!!!!!!
Tolyaha
Стоп машина, а PB1 (SCK) МК куда у Вас подключен????? Он должен быть подключен к входу SCLK АЦП (пин 1). А на вход CLK (пин 2) АЦП можно подать 60кГЦ от другого источника (только не такт от SPI), а можно и не подавать и использвать внутренний генератор АЦП.
Схему покажете, меньше вопросов будет.

ЗЫ: CS АЦП подключи на общий, и на 15 пине АЦП (DOUT), который должен быть подключен к MISO МК, исправный АЦП по умолчанию будет выдавать 4 Hz частоту.
ADEPTPS
Подсоединено все правильно, так как использую отладочную плату AS-megaCU.
Схема с сайта производителя (PDF)


- Общая информация об отладочной плате



//////Похоже одна проблема ясна: Я ничего не подаю на CLK и в настройках указал использовать External source 64kHZ
ADEPTPS
Настроил внутренний источник 64кГЦ, эффект тот же, попробовал вывести частоту на CLK - на осциллографе 0В....
Tolyaha
Цитата(ADEPTPS @ Dec 29 2011, 16:14) *
//////Похоже одна проблема ясна: Я ничего не подаю на CLK и в настройках указал использовать External source 64kHZ


По схеме на SPI висят еще микросхемы ЦАП и FLASH.

Чтобы небыло конфликта предлагаю так:
- выключить ЦАП и FLASH, PB7 и PE7 настраиваем на выход лог. "1";
- включаем АЦП, PE2 настраиваем на выход лог. "0".

Потом проверяем связь, как предлогалось ранее (чтением статус регистра).

Дальше работаем с АЦП от внутреннего (Internal 64 kHz Clock.) CLK.
Позднее, если необходимо, можно подать и внешний такт от таймера 3 МК на выход OC3A (например режим Clear Timer on Compare Match (CTC) Mode).

Успехов и всех с наступающим Новым годом!
ADEPTPS
ЦАП и FLASH - опционально устанавливаются - ИХ НЕТ!!!
из дополнительных есть только опорник и АЦП!

И Вас с Наступающим!!!
Tolyaha
Тогда проверяем связь.
CODE


PORTB = 0xff;
DDRB = 0x87;
PORTE = 0x80;
DDRE = 0x84;
#define CPOL 3
#define CPHA 2
#define SPE 6
#define MSTR 4
#define SPR0 0
#define SPIF 7
SPCR |= (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA);
for (i = 0; i < 4;i++) spi_rw(0xFF);
_delay_ms(1000);
/*проверкка связи с АЦП */
spi_rw(0x40);//настройка АЦП для чтения STATUS регистра
spi_rw(0xFF);//должно прочитаться 0x80 (AD7792)/0x88 (AD7793)

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


Пробуем, если не попутал должно прочитать 0x80 (AD7792)/0x88 (AD7793)
ADEPTPS
выдает 0... АЦП что-ли накирнулось...
Tolyaha
Цитата(ADEPTPS @ Dec 30 2011, 09:37) *
выдает 0... АЦП что-ли накирнулось...

Проверяем АЦП:
Код
    PORTB = 0xff;
    DDRB = 0x87;    
    PORTE = 0x80;
    DDRE = 0x84;

и смотрим осциллографом на пинах АЦП:

3 пин -0;
1,16 пин -1;
15 пин - частота 4 Hz.
ADEPTPS
3 пин -0; - есть!!!
1,16 пин -1; - есть!!!
15 пин - частота 4 Hz. - нет!!!!!!!!!!!!

- Всех с прошедшими праздниками!
Вышел на работу... по прежнему сдвигов нету..
Tolyaha
Цитата(ADEPTPS @ Jan 10 2012, 07:00) *
15 пин - частота 4 Hz. - нет!!!!!!!!!!!!

Значит АЦП не работает. Правда я ошибся там не 4 Hz должно быть, а 16 Hz.
ADEPTPS
тогда придется перепаивать...
yanvasiij
Люди, если все получилось поделитесь исходниками для работы с ad7792, если не жаль sm.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.