Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Микроконтроллеры (MCU) и микропроцессоры (MPU) > код с DS1990A


Автор: Vilandrew 26.12.2008, 11:45
C наступающим Новым Годом!
Возникла вот какая проблема. Программа считывает код с DS1990, но как оказалось неверно, например на выходе у меня получается в 16-ричном виде F2242424FC279F27. По даташиту DS1990 выяснилось что 64-битный код состоит из 3 частей: первые 8 бит - родительский код (должен быть 01), 48 бит сам серийный номер, остальные 8 бит - CRC. Играл с задержками при чтении, результата не дало, не могу добиться 01.
Краткое описание программы: Контроллер опрашивает считыватель, как только появился сигнал присутствия, передает команду 0x33. Затем начинает считывать и заносить 0 и 1 в двухмерный массив. По окончанию вывожу массив в порт. На компьютере анализирую полученный код и передаю одну из команд на МК. Он принимает и на основании команды зажигает один из светодиодов.
Вот сама программа:
Код

#include <avr/io.h>
#include <avr/iom128.h>
#include <stdio.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define F_CPU 8000000UL  // 8 MHz

//Инициализация UART
void Init_UART0(void)
{
UCSR0A = 0x0;        //    0000 0000
UBRR0H=0x0;        
UBRR0L=0x33;                // скорость 9600 при 8MHz
UCSR0B |= (1<<RXEN0) | (1<<TXEN0);
UCSR0C |= (1<<UCSZ01) | (3<<UCSZ00);
}

//Чтение из UART
char _get(void)        
{
        while ( !(UCSR0A & (1<<RXC0)) );    // Ждем пока данные не приняты
        return UDR0;   // Возвращаем содержимое UDR0

}

//Вывод символа в UART
void _put(char data)
{
        while ( !( UCSR0A & (1<<UDRE0)) );    // Ждем,если предыдущий символ не передался.
        UDR0 = data;                        // Кладем данные в регистр UDR0

}

void send_ds1990_command(unsigned char command);
void read_ds1990(void);
unsigned char tcnt, i;
char buffer[8][8];

//Вывод массива
void port_output(void)
{
for (int n = 0; n < 8; n++)
    {
        for(int n2 = 0;n2 < 8; n2++)
        {
        _put(buffer[n][n2]);
        }
    }    
}

//Функция сброса DS1990
void reset_ds1990(void)
{
DDRB|=_BV(0);        // Вывод порта настраиваем как выход
PORTB&=~_BV(0);

cli();
_delay_ms(0.680); //Устанавливаем 0 в теч. около 480 мкс

DDRB&=~_BV(0);       //Вывод порта настраиваем как вход
_delay_ms(0.07);  //Ожидание сигнала присутствия 70 мкс
   if(PINB & (1<<PINB0))  //Если 1 - нет сигнала присутствия
   {
   _delay_ms(0.41); //410 мкс
   sei();
   }   
  else
  {
  _delay_ms(0.41); //410 мкс
  sei();
  send_ds1990_command(0x33);
  read_ds1990();
  }
}

//Чтение

void read_ds1990(void)
{ 
cli(); 
  for(i = 0; i < 8; i++) // байтовый цикл
  {

    for(tcnt = 0; tcnt < 8; tcnt++)          // битовый цикл
    {
    DDRB|=_BV(0);
    PORTB&=~_BV(0);
    _delay_ms(0.006);// ждем 6 мкс
    DDRB&=~_BV(0);
    PORTB&=~_BV(0);
    _delay_ms(0.009); // ждем 9 мкс
          
            if(PINB & (1 << PINB0))
            {
            buffer[i][tcnt] = '1';
            }
            else
            {
            buffer[i][tcnt] = '0';
            }
    }
    _delay_ms(0.044);
 }
port_output();

unsigned char rec = _get(); // приходит команда от ПК
switch( rec )
    {
    case 'a': PORTC = 0x20; _delay_ms(4000); PORTC = 0x00; break; //зеленый
    case 'b': PORTC = 0x08; _delay_ms(2000); PORTC = 0x00; break; //красный
    default: break;
    }
sei();
    
}

//Функция пересылки команд

void send_ds1990_command(unsigned char command)
{
cli();
unsigned char data=command;
   for(i=0;i<8;i++)
   {
   data=data<<7;        //Сдвиг на i разрядов влево
   command=command>>1;  //Сдвиг передаваемого байта
     if(data==0x00)       //Передача лог.0
     {
     DDRB|=_BV(0);
     PORTB&=~_BV(0);
     _delay_ms(0.06);  //60 мкс
     DDRB&=~_BV(0);
     PORTB&=~_BV(0);          
     _delay_ms(0.01);  //10 мкс
     }
     else                 //Передача лог.1
     {
     DDRB|=_BV(0);
     PORTB|=_BV(0);     
     _delay_ms(0.006);   //Задержка примерно на 6 мкс
     DDRB&=~_BV(0);  
     PORTB&=~_BV(0);    
     _delay_ms(0.064);   //Задержка примерно на 64 мкс  
     }
   data=command;        //Новое значение для сдвига
   };
sei();
}

int main (void)
{
Init_UART0();
DDRC = 0xff;

    while (1)
    {
    reset_ds1990();
    }
}

Автор: Den64 26.12.2008, 16:07
Отлаживать через JTAG есть возможность?

Добавлено через 26 секунд
Отлаживать через JTAG есть возможность?

Автор: Vilandrew 26.12.2008, 20:17
Возможности отлаживать через JTAG нет.

Автор: xvr 26.12.2008, 20:44
У меня идиотский вопрос - а функция _delay_ms умеет принимать double параметры? Мне почему то кажется, что она ожидает целое (увы не могу проверить, нет под рукой winavr)

Автор: Vilandrew 26.12.2008, 23:52
xvr, _delay_ms принимает числа в формате double.

Автор: Den64 27.12.2008, 02:44
А частоту контроллера проверяли?
И частоту UART?
Проверить правильно ли работает UART:
Код

int main (void)
{
Init_UART0();
DDRC = 0xff;
_put(_get());
    while (1)
    {
    reset_ds1990();
    }
}


Автор: Vilandrew 27.12.2008, 14:47
Да, через fuses я уже переключил контроллер на 8Мгц. UART работает правильно, что передаю, то и получаю.
Также проверяю программу через протеус, и там почему-то тоже не выходит 01H в коде.
Если брать демонстрационный пример в протеусе (codevision) с работой 1-wire, то 01H в коде есть.

Автор: Vilandrew 27.12.2008, 19:32
Переписал программу на Codevision, все стало считываться правильно smile smile 

Автор: xvr 27.12.2008, 22:47
Цитата(Vilandrew @ 26.12.2008,  11:45)
C наступающим Новым Годом!
Возникла вот какая проблема. Программа считывает код с DS1990, но как оказалось неверно

Специально скачал winavr и посмотрел. Вот неправильный кусок:

Код

#include <avr/io.h>
#include <avr/iom128.h>
#include <stdio.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define F_CPU 8000000UL  // 8 MHz
Строка #define F_CPU 8000000UL  должна быть ДО строки #include <util/delay.h>, иначе все задержки считаются с частотой по умолчанию (1 MHz), он кстати, должен выдавать соотвествующее предупреждение

Автор: Vilandrew 28.12.2008, 14:44
xvr, да, действительно в этом и была ошибка. Но предупреждений не было.
Задержки поставил по даташиту. Еще ошибку обнаружил что делал задержку в байтовом цикле, а надо было в битовом.
Спасибо за помощь smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)