Новичок и собака

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 5
Зарегистрирован: Чт июн 13, 2013 08:29:53

Сообщение Sweeper »

Всем привет.
Делаю я тут проект радиотермометра на attiny2313. Вроде всё готово, всё работало, но что-то жрал передатчик много. Батарейки долго не проживут.
Решил ввести режим сна. С просыпанием через ватчдог, каждую секунду, и с отсылкой температуры на каждой девятисотой секунде (раз в 15 минут). И ничего не работает :(. Отсылает температуру после пробуждения, и..засыпает мертвым сном. Больше не просыпается.
Укажите на ошибку, пожалуйста!
Спойлер

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

#define F_CPU 8000000UL		// Тактовая частота микроконтроллера 8 МГц

// Подключаю стандартные библиотеки
#include <avr/io.h>			// Ножки ввода-вывода
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/interrupt.h> // работа с прерываниями
#include <util/delay.h>		// Задержки
#include <stdlib.h>


// Датчик DS18B20 - любая свободная ножка МК
#define DS18B20			5
#define DS18B20_PORT	PORTD
#define DS18B20_PIN		PIND
#define DS18B20_DDR		DDRD

uint8_t DS_scratchpad[9] = {0,0,0,0,0,0,0,0,0};	// 9 байт, считанных с DS18B20, или так называемый "блокнот"
uint8_t Presense_errors = 0;		// Счётчик ошибок - инициализация DS18B20
uint8_t Short_circuit_errors = 0;	// Счётчик ошибок - КЗ линии данных DS18B20
int8_t Temperature = 0;				// Температура преобразованная (целая часть градусов)


#define DELAY 50000			// настройка скорости (частоты)
#define WAIT_DELAY 5

#define RF_PORT PORTD		// порт передачи
#define RF_PIN  PIND		// порт чтения
#define RF_DDR  DDRD

#define OUT_PIN 6			// линия передачи
#define IN_PIN  0			// линия чтения

#define SET(r, b) (r |= (1 << b))  // установка бита порта
#define CLR(r, b) (r &= ~(1 << b)) // сброс бита порта

#define OUT_LOW  (CLR(RF_PORT, OUT_PIN))  // низкий уровень CE
#define OUT_HIGH (SET(RF_PORT, OUT_PIN))  // высокий уровень CE

#define BIT(p,b)                (b)

#define PORT(p,b)               (PORT ## p)
#define PIN(p,b)                (PIN ## p)
#define DDR(p,b)                (DDR ## p)


#define Set_Port_Bit(p,b)       ((p) |= _BV(b))
#define Clr_Port_Bit(p,b)       ((p) &= ~_BV(b))
#define Tgl_Port_Bit(p,b)       ((p) ^= _BV(b))

#define Get_Port_Bit(p,b)       (((p) & _BV(b)) != 0)


//user functions:
#define bit(io)	                BIT(io)
#define port(io)                PORT(io)

#define pin_high(io)            Set_Port_Bit(PORT(io),BIT(io))
#define pin_low(io)             Clr_Port_Bit(PORT(io),BIT(io))
#define pin_toggle(io)          Tgl_Port_Bit(PORT(io),BIT(io))

#define get_output(io)          Get_Port_Bit(PORT(io),BIT(io))
#define get_input(io)           Get_Port_Bit(PIN(io),BIT(io))

#define set_dir_in(io)          Clr_Port_Bit(DDR(io),BIT(io))
#define set_dir_out(io)         Set_Port_Bit(DDR(io),BIT(io))
#define dir_toggle(io)          Tgl_Port_Bit(DDR(io),BIT(io))
#define LED_POWER D,PD1
#define LED_START D,PD4
#define LED_DATA D,PD3
#define LED_CRC D,PD2

typedef struct {
	unsigned char start;
	unsigned char temp;
	unsigned char control_code;
	} RFpacket;
// Инициализирую DS18B20
void DS18B20_init (void)
{
	if ((DS18B20_PIN & (1 << DS18B20)) == 0) Short_circuit_errors++; // Проверяю КЗ линии данных
	DS18B20_PORT &= ~(1 << DS18B20); // Устанавливаю низкий уровень
	DS18B20_DDR |= (1 << DS18B20);
	_delay_us(490);
	DS18B20_DDR &= ~(1 << DS18B20);
	_delay_us(68);
	if ((DS18B20_PIN & (1 << DS18B20)) > 0) Presense_errors++; // Ловлю импульс присутствия датчика
	// Если датчик не подключен, Presense_errors увеличиваю на 1
	_delay_us(422);
}


// Функция чтения байта из DS18B20
uint8_t DS18B20_read (void)
{
	uint8_t dat = 0;
	for (uint8_t i=0; i<8; i++)
	{
		DS18B20_DDR |= (1 << DS18B20);
		_delay_us(2);
		DS18B20_DDR &= ~(1 << DS18B20);
		_delay_us(4);
		dat = dat >> 1;
		if (DS18B20_PIN & (1 << DS18B20))
		{
			dat |= 0x80;
		}
		_delay_us(62);
	}
	return dat;
}


// Функция чтения "блокнота" из DS18B20
void DS18B20_read_scratchpad (void)
{
	for (uint8_t i=0; i<9; i++)	// Считываю 9 байт данных, или так называемый "блокнот"
	{
		DS_scratchpad[i] = DS18B20_read();
	}
}


// Функция записи байта в DS18B20
void DS18B20_write (uint8_t dat)
{
	for (uint8_t i=0; i<8; i++)
	{
		DS18B20_DDR |= (1 << DS18B20);
		_delay_us(2);
		if (dat & 0x01)
		{
			DS18B20_DDR &= ~(1 << DS18B20);
		}
		else
		{
			DS18B20_DDR |= (1 << DS18B20);
		}
		dat = dat >> 1;
		_delay_us(62);
		DS18B20_DDR &= ~(1 << DS18B20);
		_delay_us(2);
	}
}


// Алгоритм для вычисления CRC-8 для DALLAS.
// Для первого байта CRC = 0, для остальных - то, что получилось от предыдущего.
// В расчёт CRC входят первые 8 байт DS18B20.
// 1. Нахождение логического исключающего ИЛИ между младшим битом CRC и младшим битом данных. 
// 2. Если результат равен 0, то:
//    - Сдвиг вправо CRC.
// 3. Если результат равен 1, то:
//    - Поиск нового значения CRC путем вычисления логического исключающего ИЛИ между CRC и полиномом CRC.
//    - Сдвиг вправо CRC.
//    - Установка старшего бита CRC в 1. 
//    - Сдвиг вправо данных. 
//    - Повтор данной последовательности 8 раз на 1 байт данных.
uint8_t DS18B20_crc (uint16_t adress)
{
	uint8_t crc = 0;			// Переменная для накопления CRC
	for (uint8_t i=0; i<8; i++)	// Считаю CRC 8-ми байт, 9-й байт это CRC
	{
		// Расчитываю CRC одного байта
		crc = crc ^ (*(uint16_t*)(adress+i));
		for (uint8_t j=0; j<8; j++)
		{
			if (crc & 0x01) crc = (crc >> 1) ^ 0x8C;
			else crc >>= 1;
		}
	}
	return crc;	// Возвращаю CRC
}
unsigned char CC_my(int temp, int start){//ControlCode_my
	unsigned char val = temp;
	for (uint8_t i=0; i<8; i++){
		val=val^start;
		val=val >> 1;
	}
	return (unsigned char)val;
}
void RF_init()
{
	/*настройка входа и выхода*/
	RF_DDR  = (1<<OUT_PIN)|(0<<IN_PIN);
	RF_PORT = (1<<OUT_PIN)|(1<<IN_PIN);
	set_dir_out(LED_POWER);
	set_dir_out(LED_START);
	set_dir_out(LED_DATA);
	set_dir_out(LED_CRC);
}
// передача байта
void RF_write(unsigned char data){
	unsigned char i;
	for(i = 0; i < 8; i++){ // передача данных
		if(((data >> 7) & 1)) { // получение одного бита для передачи
			OUT_HIGH; // передача единицы
			} else {
			OUT_LOW;  // передача нуля
		}
		_delay_us(DELAY);
		data <<= 1;
	}
}
void transmit(RFpacket rfp){
	for (uint8_t i=0; i<100; i++){
		pin_high(LED_START);
		RF_write(rfp.start);
		pin_low(LED_START);
		OUT_LOW;
		_delay_ms(WAIT_DELAY);
			
		pin_high(LED_DATA);
		RF_write(rfp.temp);
		pin_low(LED_DATA);
		OUT_LOW;
		_delay_ms(WAIT_DELAY);

		pin_high(LED_CRC);
		RF_write(rfp.control_code);
		pin_low(LED_CRC);
		OUT_LOW;
		_delay_ms(WAIT_DELAY);
	}
}
volatile int count=900; // начинаем сразу с нужного значения, для того чтоб со старта отправить
//#define debug //раскомментить для протеуса

// в протеусе работат только Idle, в реальном же железе будем использовать PWR Down
#ifdef debug 
	#define sleep() OUT_LOW;\
	set_sleep_mode(SLEEP_MODE_IDLE);\
	sleep_mode();
#else
	#define sleep() OUT_LOW;\
	set_sleep_mode(SLEEP_MODE_PWR_DOWN);\
	sleep_mode();
#endif
ISR (WDT_OVERFLOW_vect) {
	wdt_reset();                  // reset watchdog timer
	WDTCR = (1<<WDE) | (1<<WDCE); // enable watchdog
	WDTCR = (1<<WDIE) | WDTO_1S;  // watchdog interrupt instead of reset
	count++;
}

int main (void)            
{
	RF_init();
    wdt_reset();                  // reset watchdog timer
    WDTCR = (1<<WDE) | (1<<WDCE); // enable watchdog
    WDTCR = (1<<WDIE) | WDTO_1S;  // watchdog interrupt instead of reset
	asm volatile ("sei"); // разрешаем прерывания глобально
	while(1)
	{
		if(count==900){
			count=0;
			DS18B20_init();			// Инициализирую DS18B20
			DS18B20_write(0xCC);	// Пропускаю проверку серийного номера DS18B20
			DS18B20_write(0x44);	// Запускаю температурное преобразование
			_delay_ms(1000);		// Жду окончания температурного преобразования
			DS18B20_init();			// Инициализирую DS18B20
			DS18B20_write(0xCC);	// Пропускаю проверку серийного номера DS18B20
			DS18B20_write(0xBE);	// Команда на чтение содержимого ОЗУ
			DS18B20_read_scratchpad();	// Считываю "блокнот"
			if (Short_circuit_errors | Presense_errors)	// Если датчик не отвечает на Presense-импульс, либо КЗ линии данных 
			{

			}
			else
			{
				if (DS_scratchpad[8] == DS18B20_crc(&DS_scratchpad[0]))	// Если принятая CRC совпала с расчётной CRC 
				{
					pin_high(LED_POWER);
					Temperature = (int8_t)((DS_scratchpad[1] << 4)|(DS_scratchpad[0] >> 4));	// Совмещаю младший и старший байты, отбрасываю дробную часть, получаю температуру в градусах.
					RFpacket pck;
					pck.temp=(unsigned char)Temperature;
					pck.start=0b10101101;
					pck.control_code=CC_my(pck.temp,pck.start);
					transmit(pck);
				}
				else	// Если принятая CRC не совпала с расчётной, ничего не делаем
				{

				}
			}
			Presense_errors=Short_circuit_errors=0;	// Сбрасываю счётчик ошибок инициализации DS18B20, сбрасываю флаг КЗ
			pin_low(LED_POWER);
		}
		wdt_reset();                  // reset watchdog timer
		MCUSR &= ~(1<<WDRF);          // clear reset flag
		WDTCR = (1<<WDE) | (1<<WDCE); // enable watchdog
		WDTCR = (1<<WDIE) | WDTO_1S;  // watchdog interrupt instead of reset
		sleep();
	}
}


Реклама
Ответить

Вернуться в «AVR»