AD7705 + atmega168

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

Сообщение slavokhire5 »

Всем привет. Второй день не могу оживить АЦП AD7705.
Не нравятся мне осциллограммы обмена, я как-то совсем другие ожидал увидеть.
Прикрепляю фотку. Синий луч - CS для AD7705, желтый - сигнал DRDY.

Что именно не нравится:
1. я ожидаю увидеть DRDY после выдачи последнего (4-го) байта инициализации в SPI.
Реально вижу, что DRDY опускается в нижний уровень где-то посередине 4-го байта, и подымается ровно-ровно вместе с CS (увеличивал до 1 мкс, все равно совпадает)
2. как только начинаю передавать в АЦП команду на чтение (опускаю CS), сразу же опускается и DRDY. Завершаю команду на чтение - DRDY вместе с CS подымается.
3. ситуация 2 повторяется при попытке чтения.
4. в конце DRDY повисает в "0" (я так понимаю, это сигнал о том, что данные не вычитаны)
5. при дальнейшем чтении через каждые 60 мс DRDY так ни разу и не подымается в высокий уровень... короче хрень =)

Вот куски кода:

Код: Выделить всё

int main(void)
{
	Init();
	sei();
	

	PORTB &= ~(1 << PB6);      // сброс АЦП ногой RESET
	_delay_ms(50);
	
	PORTB |= (1 << PB6);
	_delay_ms(50);

	
	ADC_Write(0x20); // Active Channel is Ain1(+)/Ain1(-), next operation as write to the clock register 
	_delay_us(50);
	ADC_Write(0x04); // master clock enabled, 2.4576MHz Clock, set output rate to 50Hz
	_delay_us(50);
	ADC_Write(0x10); // Active Channel is Ain1(+)/Ain1(-), next operation as write to the setup register 
	_delay_us(50);
	ADC_Write(0x40); // gain = 1, bipolar mode, buffer off, clear FSYNC and perform a Self Calibration
	
	_delay_us(200);
	
	while(1)
	{
		ADC_Write(0x38);
		_delay_us(10);
		ADC_Read();
		_delay_ms(60);
	}
}



void ADC_Write(uint8_t byteword)
{
	PORTB &= ~0x04;					// ADC_CS low
	SPI_Transmit(byteword);
	PORTB |= 0x04;
}
	
	
uint16_t ADC_Read(void)
{
	uint16_t adc_buf;

	PORTB &= ~0x04;					// ADC_CS low
	
	adc_buf =	SPI_Transmit(0) << 8;
	adc_buf +=	SPI_Transmit(0);

	PORTB |= 0x04;
	
	return adc_buf;
}

Пробовал убирать/добавлять/изменять задержки, менять CPOL и CPHA в настройках SPI - результат кардинально не меняется. Подскажите пожалуйста, где я туплю? =)
Вложения
IMG_20150209_121801.gif
(152.23 КБ) 353 скачивания
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
Реклама
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

Сообщение slavokhire5 »

Поборол АЦП. Работает в двухканальном режиме. Решение - CS нужно давать не на каждую команду, а на группу команд (т.е. один CS на всю инициализацию и один CS на команду чтения и само чтение). В таком случае работает нормально. Шумит, правда 1-2 разряда, но разводка у меня корявая)
Код инициализации:

Код: Выделить всё

void init_SD_ADC(uint8_t channel)
{
	int0_done = false;
	
	PORTB &= ~(1 << PB6);		// reset ADC
	_delay_ms(50);
	
	PORTB |= (1 << PB6);
	_delay_ms(50);

	PORTB &= ~0x04;				// CS ADC
	_delay_us(50);
	
	ADC_Write(0x20 | channel);	// Active Channel select, next operation as write to the clock register
	ADC_Write(0x04);			// master clock enabled, 2.4576MHz Clock, set output rate to 50Hz
	ADC_Write(0x10 | channel);	// Active Channel select, next operation as write to the setup register
	ADC_Write(0x9E);			// gain = 8, unipolar mode, buffer on, clear FSYNC and perform a Zero Calibration

	_delay_us(50);
	PORTB |= 0x04;
	_delay_us(500);
}
Код опроса АЦП:

Код: Выделить всё

if (int0_done == true) 
	{
		uint16_t data;
		
		PORTB &= ~0x04;
		_delay_us(100);
		
		ADC_Write(0x39);
		
		data =	SPI_ADC_tx(0) << 8;
		data +=	SPI_ADC_tx(0);
				
		_delay_us(100);
		PORTB |= 0x04;
		
		int0_done = false;
}
Опрос делается по прерываниям
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
Реклама
Ответить

Вернуться в «Периферия»