Перейти к содержанию
    

Как организовать одновременное управление индикаторои и опрос датчика?

Коллеги, посоветуйте.

Есть индикатор семисегментный о 4-х разрядах, сегменты соединены для динамической индикации. PORTD управляет сегментами, а PORTB.2-5 - разрядами. Есть датчик DS1820. Естественно, динамическая индикация должна коммутироваться постоянно. А датчик требует продолжительное время для считывания информации. ПРиведенный код заставляет его моргать, пока чтается информация с датчика.

 

Как организовать одновременное управление индикаторои и опрос датчика?

 

#include <mega48.h>
#include <delay.h>
#include <ds1820.h>

#asm
    .equ __w1_port=8
    .equ __w1_bit=1
#endasm

unsigned char Temp;
unsigned int interval;

unsigned char DIGIT(unsigned char dig)
{
//    7   6   5   4   3   2   1   0  , 
//    e   d   h   g   c   a   f   b

if (dig==0) return 0b11001111;
if (dig==1) return 0b00001001;
if (dig==2) return 0b11010101;
if (dig==3) return 0b01011101;
if (dig==4) return 0b00011011;
if (dig==5) return 0b01011110;
if (dig==6) return 0b11011110;
if (dig==7) return 0b00001101; 
if (dig==8) return 0b11011111;
if (dig==9) return 0b01011111;
if (dig==11) return 0b00010111;
else return 0x00;
}

/* maximum number of DS1820/DS18S20 connected to the 1 Wire bus */
#define MAX_DEVICES 8

/* DS1820/DS18S20 devices ROM code storage area */
unsigned char rom_code[MAX_DEVICES][9];


void main()

{

unsigned char i,j,devices;
int temp;



DDRD=0xFF;
DDRB=0xFF;

PORTD=0xFF;


devices=w1_search(0xf0,rom_code);


while(1)
{

interval++;
if (interval >10000) {Temp=ds1820_temperature_10(&rom_code[0][0]);interval=0;}

PORTB=0xFF;
delay_us(1);
PORTB.3=0;
PORTD=DIGIT(0);
delay_us(5);
PORTD=0x00;

PORTB=0xFF;
delay_us(1);
PORTB.4=0;
PORTD=DIGIT(9)|0b00100000;
delay_us(5);
PORTD=0x00;

PORTB=0xFF;
delay_us(1);
PORTB.5=0;
PORTD=DIGIT(6);
delay_us(5);
PORTD=0x00;


PORTB=0xFF;
delay_us(1);
PORTB.2=0;
PORTD=DIGIT(11);
delay_us(5);
PORTD=0x00;

}

Изменено пользователем murmur

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что-то не получается...

 

время обработки прерывания вышло 42 мкс. Не много ли? Не замусорит ли такое прерывание данные из DS1820?

На какую частоту настраивать прерывание?

 

#include <mega48.h>
#include <delay.h>
#include <ds1820.h>

#asm
    .equ __w1_port=8
    .equ __w1_bit=1
#endasm

unsigned char Temp,temp, cur_digit;
unsigned int interval;


flash char DIGITS[] =
{
0b11001111,
0b00001001,
0b11010101,
0b01011101,
0b00011011,
0b01011110,
0b11011110,
0b00001101,
0b11011111,
0b01011111,
0b00010111
    
};

/* maximum number of DS1820/DS18S20 connected to the 1 Wire bus */
#define MAX_DEVICES 8

/* DS1820/DS18S20 devices ROM code storage area */
unsigned char rom_code[MAX_DEVICES][9];

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTC.0=1;
PORTB=0b11110111;
PORTD=DIGITS[temp/10];
delay_us(1);
PORTD=0x00;

PORTB=0b11101111;
PORTD=DIGITS[temp%10];
delay_us(1);
PORTD=0x00;

PORTB=0b11011111;
PORTD=DIGITS[6];
delay_us(1);
PORTD=0x00;

PORTB=0b11111011;
PORTD=DIGITS[11];
delay_us(1);
PORTD=0x00;
PORTC.0=0;
}

void main()

{

unsigned char i,j,devices;
int temp;


DDRC.0=1;
DDRD=0xFF;
DDRB=0xFF;

PORTD=0xFF;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x02;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x01;

//devices=w1_search(0xf0,rom_code);
w1_init();
  #asm("sei")   

while(1)
{

// #asm("cli")
Temp=ds1820_temperature_10(0);
//  #asm("sei")
temp=(Temp>>1);

}

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что-то не получается...

 

время обработки прерывания вышло 42 мкс. Не много ли? Не замусорит ли такое прерывание данные из DS1820?

На какую частоту настраивать прерывание?

 

 

24 раза в секунду, как в кино. Прм трех индкаторах 3Х24 = 72 раза в секунду.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня тупо опрашивает один датчик, потом другой датчик, а потом проблескивает 8 разрядов индикация. И так по кругу..

 

здесь

 

Ой. Ошибочка. Девять разрядов динамической индикации. Девятый разряд для светодиодной индикации режимов.

Мерцание на глаз незаметно. Связь с датчиками по SPI.

Таймеры не используются. Все работает циклично по кругу. В том числе и настройка и ввод значений.

Изменено пользователем Слесарь

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для решения этой и многих других задач, удобно и правильно использовать автоматное программирование ->

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня тупо опрашивает один датчик, потом другой датчик, а потом проблескивает 8 разрядов индикация. И так по кругу..

Такое решение слишком примитивно в лоб. для сиюминутного подойдет, а дальше?

для "murmur"

динамическая индикация шине 1-wire мешать не должна, если она через UART никогда не помешают

или на чтение бита ставь запрет прерываниям.

в приведенном коде ерунда, какие задержки? в прерывании только надо обновить позицию, сменить знакоместо.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

24 раза в секунду, как в кино. Прм трех индкаторах 3Х24 = 72 раза в секунду.

каждое прерывание индикация выводится на 1 из 3 индикаторов, время экспозиции одного знакоместа =42мс, итого 24/3=8 раз/сек., так?

обновление дисплея 24 раза в секунду при 1 индикаторе = 24 FPS

обновление дисплея 24 раза в секунду при 2 индикаторах = 12 FPS

обновление дисплея 24 раза в секунду при 3 индикаторах = 8 FPS

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Такое решение слишком примитивно в лоб. для сиюминутного подойдет, а дальше?

Работает второй год. Несколько образцов

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Явно кривая реализация timer0_ovf_isr - у вас последовательно выводятся все индикаторы в одном вызове прерывания. Нужно добавить счетчик текущего знакоместа и выводить по одному разряду при каждом вызове прерывания. Частоту таймера достаточно сделать 400Гц или больше. Температуру выводить в отдельный буфер индикации в основном цикле. При опросе 18В20 в критических местах (в битовых задержках) запрещать прерывания.

время обработки прерывания вышло 42 мкс. Не много ли?
Это очень мало. Вот когда параллельно работают несколько таймеров, задействовано ШИМ-управление, UART, USB и нужно опрашивать несколько 1-wire устройств - это да, жопа
Изменено пользователем ukpyr

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть датчик DS1820. Естественно, динамическая индикация должна коммутироваться постоянно.

Да. Не дочитал. У меня на стиральной машине на получение данных с этого датчика уходит примерно 0,1 секунды времени. На этот промежуток динамическая индикация прерывается. Благо я опрашиваю датчик по таймеру не так часто. Хотя, я могу продумать обработчик динамической индикации и в коде обработчика 1-Wire датчика.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Получилось, но хоть ты тресни, показывает 85 градусов.

Блокирировала прерывания на время измерения - индикаторглючит - выводит по очереди цифры, но все равно видно что 85 градусов. Подключала как по классической схеме, так и по паразитному питанию.

 

ЧТо не так?

#asm
    .equ __w1_port=0x08
    .equ __w1_bit=1
#endasm

#include <mega48.h>
#include <stdio.h>
#include <delay.h>
#include <ds1820.h>
#include <1wire.h>


unsigned char cur_digit;
unsigned int Temp;

unsigned char dig[4];

flash char DIGITS[] =
{
0b11001111,
0b00001001,
0b11010101,
0b01011101,
0b00011011,
0b01011110,
0b11011110,
0b00001101,
0b11011111,
0b01011111,
0b00010111
    
};



/* maximum number of DS1820/DS18S20 connected to the 1 Wire bus */
#define MAX_DEVICES 8

/* DS1820/DS18S20 devices ROM code storage area */
unsigned char rom_code[MAX_DEVICES][9];

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
PORTD=0x00;
if (cur_digit==3) cur_digit=0;else cur_digit++;
PORTB = 0xFF &(~(1<<cur_digit+2));
PORTD=DIGITS[dig[cur_digit]];
}

void main()

{

unsigned char i,j,devices;
int temp;


DDRC.0=1;
DDRD=0xFF;
DDRB=0xFF;

PORTD=0xFF;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x03;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x01;

//devices=w1_search(0xf0,rom_code);
w1_init();
devices=w1_search(0xf0,rom_code);
#asm("sei")   

dig[3]=0;
dig[0]=11;    PORTB=0x00;
PORTD=0x00;
while(1)
{
//  #asm("cli")

Temp=ds1820_temperature_10(&rom_code[0][0])/10;
//  #asm("sei")

//dig[1]=devices;
dig[1]=Temp/ 10;
dig[2]=Temp % 10;




}

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Получилось, но хоть ты тресни, показывает 85 градусов.

У меня тоже кажись показывало 85 градусов когда неправильно инициализиповал датчик перед запросом значения температуры.

Сейчас поищу код, если нацду, представлю

 

Вот, когдат делал

 

char ds18b20_init(void) 
{ 
    unsigned char c = 0;  
    PORTBbits.RB4 = 1; // импульс сброса 
    DelayUs( 200 ); 
    DelayUs( 200 ); 
    DelayUs( 200 ); 
    DelayUs( 200 ); 
    PORTBbits.RB4 = 0; 
    DelayUs( 1 ); 
    while( PORTAbits.RA2 == 0 ) // Дождаться ответа чипа о готовности 
    { 
        DelayUs( 1 ); 
        c++; 
        if( c > 20 ) return 0; 
    }      
    if( c < 4 ) return 0; 

    DelayUs( 1 ); 
    c = 0; 
    while( PORTAbits.RA2 == 1 ) // Дождаться нормализации 
    { 
        DelayUs( 10 ); 
        c++; 
        if( c > 20 ) return 0; 
    }      
    if( c < 3 ) return 0; 

    DelayUs( 1 ); 
    return 1; 
}  

void ds18b20_write_bit( char b) 
{  
    PORTBbits.RB4 = 1;  

       if( b == 1 ) 
    {  
          DelayUs(1);         //min 1us 
        PORTBbits.RB4 = 0; 
     }  

    DelayUs( 60 ); // 20 ... 
    PORTBbits.RB4 = 0; 
    DelayUs(1);          
}  

void ds18b20_write_byte( char B ) 
{  
    char i, aux;  
     
    for( i=0; i<8; i++ ) 
    {  
        aux = B >> i;      
        aux &= 0x01;        
        ds18b20_write_bit(aux);  
    } 
}  

char ds18b20_read_bit(void) 
{ 
    char ret; 
    char tick = 0; 
    PORTBbits.RB4 = 1; // импульс сброса 
    DelayUs(1);         //min 1us  
    PORTBbits.RB4 = 0;  
    DelayUs(1);         //min 1us  

    while( PORTAbits.RA2 ) 
    { 
        DelayUs(1); 
        tick++; 
    } 

    if( tick > 4 ) return 0; 

    DelayUs( 50 );  

    return 1;   
}  

char ds18b20_read_byte(void) 
{ 
   char i, result=0x00;  
    
    for( i=0; i < 8; i++ ) 
    {  
      if( ds18b20_read_bit() ) result |= (0x01 << i);  
    }  
       return result;  
} 

signed float GetTemp() 
{ 
    char i; 
   unsigned char scratchpad_data[9];  
   signed float temperature; 

    if( !ds18b20_init() ) Error( 2 ); // если что-то пошло не так 
    ds18b20_write_byte(0xCC); 
    ds18b20_write_byte(0x44); 
    while( PORTAbits.RA2 ); 
    if( !ds18b20_init() ) Error( 2 );  
    ds18b20_write_byte(0xCC); 
    ds18b20_write_byte(0xBE); 

    for( i=0; i < 9; i++ ) 
    {  
         scratchpad_data[i] = ds18b20_read_byte();  
    } 
  
    if( scratchpad_data[5] != 0xFF ) Error( 2 ); 
    if( scratchpad_data[7] != 0x10 ) Error( 2 ); 

    temperature = ( scratchpad_data[0] * 0.0625 ) + ( scratchpad_data[1] * 16 );  

    return temperature; 
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У вас какой-то странный код. Что за ответ "готовности от чипа"? ДЛя чего контроль ножки на PORTA?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проблема решилась - оказалось датчик не хочет рабоать в паразитном режиме.

Причем он работает, когда нога VDD вообще висит в воздухе!!!!!!

 

Это может быть связано с самим датчиком?

 

Я не проектирую устройство с нуля, я заново переписываю прошивку для уже готового устройства, в котором сгорел контроллер, а прошивки нет...

Изменено пользователем murmur

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...