Anonymní profil Jirka – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Anonymní profil Jirka – Programujte.comAnonymní profil Jirka – Programujte.com

 

Příspěvky odeslané z IP adresy 89.102.182.–

Lotus
Mikrokontroléry › ATmega16 & AD7688
25. 2. 2013   #172055

Ale musím říct, že zase taková prkotina, tím myslím, že stačilo změnit výpis na jiný datový typ a ejhle už to frčí. 

Ale děkuji za vaše rady a postřehy. Teď už by to mohlo být OK. Zítra zkusím kouknout na tu komunikaci logickým analyzátorem.

Lotus
Mikrokontroléry › ATmega16 & AD7688
25. 2. 2013   #172053

#15 Lotus
Ale pozor. Změnil jsem nastavení CPOL a CPHA. Obojí do 1.

A teď při měření 1,71V jsem dostal 5887H (v dec je to 22663) a podle výpočtu mám dostat 22413. A to už je asi nejblíž.

Při 2.31V 7710H (dec 30480) a výpočet říká 30277.

Nyná už to vypadá zajímavěji.

Lotus
Mikrokontroléry › ATmega16 & AD7688
25. 2. 2013   #172051

Tak jsem ten výpis hodil do HEXa.

A po nastavení 0V, jsem dostal na LCD hodnotu fffc

Při 4,97V LCD ukazuje 7fb1

Lotus
Mikrokontroléry › ATmega16 & AD7688
25. 2. 2013   #172050

No a ještě k tomu HW, jestli není chyba zde:

Zapojil jsem to takto: IN- jsem uzemnil, protože chci měřit v rozmezí 0-5V a na IN+ jsem připojil ono měřené napětí.

A ostatní jsem ošetřil z datasheetu.

Jinak zítra koupím ještě jeden obvod pro můj logický analyzátor a pokud se zadaří, tak průběhy s ním odměřím a dám je sem. Toto by mi určitě hodně pomohlo.

Lotus
Mikrokontroléry › ATmega16 & AD7688
25. 2. 2013   #172044

Tak to mám jeden malý problém. Nemám osciloskop.

CPHA & CPOL jsem prokombinoval mezi sebou. Pouze když byly oba v 1, tak se výsledek změnil. Ale změnil se k nepoznání (dostal jsem záporné číslo úplně mimo mísu).

A v ostatních kombinacích se číslo zobrazuje kladné, ale cca 2x menší.

Lotus
Mikrokontroléry › ATmega16 & AD7688
25. 2. 2013   #172041

Tak já jsem se silama už v koncích. Nikoho nic nenapadá?

Lotus
Mikrokontroléry › ATmega16 & AD7688
24. 2. 2013   #172026

Tak jsem nastavil ten CPHA do 1 a nic. Výsledek pořád stejný.

Lotus
Mikrokontroléry › ATmega16 & AD7688
24. 2. 2013   #172023

#5 KIIV
No mám to zapojené podle "CS MODE 3-WIRE, NO BUSY INDICATOR"

Lotus
Mikrokontroléry › ATmega16 & AD7688
24. 2. 2013   #172016

Nyní jsem ve fázi, že hodnota zobrazená na LCD je malá. cca 2x menší než má být. A CPOL a CPHA v datasheetu není uvedené jak nastavit, tak jsou v 0. Ale s nima jsem experimentoval, takže zde chybu nevidím. Neporadí někdo? Kód je zde:

#include <avr/io.h>  
#include <stdio.h>
#include <stdlib.h>  
#include <util/delay.h>  
#include <avr/interrupt.h> 

#include "lcd.h"  

// Mega16 Pinout
#define MOSI	5
#define MISO	6
#define SCLK	7
#define SS		4

char buffer[20];

unsigned int get_adc(unsigned char adata)
{
   static unsigned int temp=0;

	_delay_ms(1);
	PORTB &= ~(1<<SS);               // SET CS to LOW (activate ADC)
	_delay_us(2);                  // small dealy
	SPDR = adata;                 
	while(!(SPSR & (1<<SPIF)));     //MSB           
	temp = SPDR;                 
	temp <<=8;    //shift to upper byte                 
	SPDR = adata;                 
	while(!(SPSR & (1<<SPIF)));     //LSB
	temp += SPDR;     // add low byte
	   //temp <<=8;      // why this??
	PORTB |= (1<<SS);               // SET CS ti HIGH (stop 
	return temp;
}

void spim_init(void)
{
	// SET PORT B jako výstup 
	DDRB |= (1<<MOSI) | (1<<SCLK) | (1<<SS);
	// SET MISO jako vstup
	DDRB &= ~(1<<MISO); 
	// Povoleni SPI, SPI Master, LSB First, SPI CLK XTAL/16)
	SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0);	
	// nastaveni funkcniho registra SPI (SPCR), CPHA a CPOL v log 0
	SPCR &= ~ (1<<CPOL); 
	SPCR &= ~ (1<<CPHA);	
	// CS HIGH protože SPI ADS je aktivní v 0
	PORTB |= (1<<SS);		 
}
  
int main(){  
	static unsigned int adc_value=0;	// promenna AD prevodniku
	spim_init();

    lcd_init(LCD_DISP_ON); //inicializacia displeja  

	for(;;){

	adc_value = get_adc(0xff);				// získání hodnoty z AD prevodniku

	lcd_gotoxy(0,1);
	sprintf(buffer,"ADC: %05d",adc_value);		//zobrazi na LCD hodnotu adc_value na 4 místa (0000)
	lcd_puts(buffer);
	
	}
return 0;  
}
Lotus
Mikrokontroléry › ATmega16 & AD7688
22. 2. 2013   #171821

Tak jsem něco sesmolil, ale hodnoty mi trošku lítají od mínus do plus,... :-D

unsigned int get_adc(unsigned char adata)
{
static unsigned int temp=0;

PORTB &= ~(1<<SS);     // aktivace ADC
_delay_us(2);      // prodleva 1us
SPDR = adata;      
while(!(SPSR & (1<<SPIF)));   // Poslat 1 byte přes HW SPI a čeka na tx (příjem MSB)
temp = SPDR;      
temp <<=8;       // posune proměnnou TEMP o 8 vlevo
SPDR = adata;      
while(!(SPSR & (1<<SPIF)));   // Poslat 1 byte přes HW SPI a čeka na tx (příjem LSB)
temp += SPDR;      // kombinace dat
temp <<=8;
PORTB |= (1<<SS);     // nastavi CS do 1 a tim zakaze ADC
return temp;      // navratí 16-bit hodnotu ADcka
_delay_us(4);
}
Lotus
Mikrokontroléry › ATmega16 & AD7688
22. 2. 2013   #171819

Dobrý večer pánové,

chtěl bych se zeptat, jestli jsem dobře pohopil komunikaci s AD7688 převodníkem.

Jako první jen uvedu zapojení (Mega16 = AD7688): MISO = SDO, SCK = SCK, SS = CNV

A vývod SDI spojen s VIO, takže chci komunikovat s "CS mode 3-wire, no busy indicator".

A teď ke komunikaci.

Jako první musím vytvořit impulz na pinu SS s délkou 10ns a poté následuje zvednutí SS po dobu 1us do jedničky. Po uplynutí této doby hodit SS do nuly a vyčítat 16bitů z MISO. Po přečtení 16 bitů SS do jedničky a vyčkat 2us (time between conversion". No potom už to volat pořád dokola jak chci. Je to tak správně? děkuji za odpověď.

Vyčítal jsem to z obrázku 35 (str. 17) a hodnoty časů (str. 5) z datasheetu

http://www.analog.com/static/imported-files/data_sheets/AD7688.pdf

Pinzeta
Mikrokontroléry › Signály CS a FS u TLC4541
12. 2. 2013   #171459

#2 KIIV
Takže na komunikaci mi stačí pouze SCLK a SDO? to je hustý. :-D Díky moc KIIVE

Pinzeta
Mikrokontroléry › Signály CS a FS u TLC4541
12. 2. 2013   #171456

Ahojte přátelé. :-)

Prosím mohl bych mít jednoduchý, dotaz?

Splašil jsem AD převodník TLC4541, ale nějak nemůžu přijít jak jej připojit k AVRku.

Vývody VDD, AIN, GND jsou mi jasné.

SDO = je výstup (přijímám  2 Byte)

SLCK = zdroj hodin

[b]

a teď: CS slouží k vybrání zařízení na sběrnici, ale zároveň, pokud jsem to dobře pochopil, mě informuje, jestli přijímám MSB nebo LSB z výstupu SDO.

Ale nač je tam FS? Nemohl bych ho jednoduše připojit na +5V?[/b]

Podotýkám, že zařízení je samo na sběrnici. Děkuji za radu

Jirka
C / C++ › chyba při kompilaci DEV-C++
3. 2. 2013   #171087

#1 Jirka
Takže jsem to opravil.

Nevím co se stalo ale byla tam někde chyba. :-D

Takže jsem provedl tyto změny.

Nástroje-Nastavení kompilátoru.

Záložka adresáře a tam jsem postupoval tak, že jsem smazal odkazy na adresáře DEV-C++ a nahradil jsem je odkazama na MinGW

Jirka
C / C++ › chyba při kompilaci DEV-C++
3. 2. 2013   #171085

Ahoj.

PLS ve škole programujeme v DEV-C++, a ten program chci mít i u sebe na notebooku, abych mohl dělat projekty.

No ale problém je ten, že se mi nedaří nic zkompilovat. A strejda google taky nepomohl.

Udělal jsem si jednoduchý program. Má pouze vypsat něco do konzole, ale ne a ne to rozjet. Poradí někdo?

Více info na obrázku.

Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
30. 1. 2013   #170859

#22 KIIV
Ano to s tím vymaskováním toho posledního bitu "7F" mě taky napadlo a tak jsem s tím začal operovat, ale zapomněl jsem změnit to rotování na 3. Tak proto mě to nějak něchtělo jet. Už to vypadá OK. Teď se už jenom poperu s tím zobrazením, ale to by už měla být "hračka".

Takže znova KIIVE Dík 

Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
30. 1. 2013   #170855

tak jsem zase zpět. 

Tady jsem si sesmolil kus kódu, ale mám problém. Přijímám hodnoty z AD od 2048 do 4095. A nemůžu to rozslousknout.

A zakopaný pes bude tady.

unsigned int get_adc(unsigned char adata)
{
	static unsigned int temp=0;
	
	PORTB &= ~(1<<SS);		// SET CS do 0 (aktivovani ADC) 
	_delay_us(10);			// zde by měla být krátká prodleva??
	SPDR = adata;			// vložit data do odesílací registru
	while(!(SPSR & (1<<SPIF)));	// Poslat 1 byte přes HW SPI a čeka na tx
	temp = SPDR;			// přijatá data nahraje do proměnné TEMP
	temp <<= 8;			// posune proměnnou TEMP o 8 vlevo
	SPDR = adata;			// vloží data do odesílacího registru
	while(!(SPSR & (1<<SPIF)));	// Poslat 1 byte přes HW SPI a čeka na tx	
	temp += SPDR;			// combine data
	temp >>=4;			// posune proměnnou TEMP o 4 vpravo
	PORTB |= (1<<SS);		// nastavi CS do 1 a tim zakaze ADC 
	return temp;			// navratí 12-bit hodnotu ADcka
}

Ono to vypadá, jak kdybych přijímal pouze část 12-bitů. Takže jsem si myslel, že je špatné rotování, ale to jsem nakonec vyloučil. Takže chyba asi bude ve slučování (temp += SPDR;) Ale prč takto nemůžu kombinovat čísla?

Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
29. 1. 2013   #170803

áááááááááááááááááááááá já z toho vyrostu. :-D

Tak stačilo změnit printf na sprintf a už to vypadá dobře. :-D :-D :-D :-D :-D :-D

Děkuji děkuji

PS: to by mě zajímalo, kolik takových chyb mě ještě čeká. :-D

Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
29. 1. 2013   #170800

Ano to jsem si vložil do cyklu for, kde to opakuju. Zdroj jsem připojil přímo k tomu AD převodníku a zkouším to. Ale bez odezvy.

Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
29. 1. 2013   #170797

A teď jsem si všiml, že ten modul AD převodníku je blbě. Ten trimr takto nemůže být připojený.

Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
29. 1. 2013   #170796

#12 hlucheucho
Ano tak s tím CPOL a CPHA jsi měl pravdu. To jsem měl nastavené blbě, nebo spíš vůbec. A na ty porty jsem se díval a vypadá, že je vše jak má, ale program furt nic.

Ale normálně na tvrdo jsem si vytiskl tu proměnnou lcd_puts(adc_value); a čekal jsem, že se ta hodnota bude měnit, že se displej zblázní, že bude ukazovat ptákoviny, ale místo toho tam pořád svítí 100.  A nic se neděje.

Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
29. 1. 2013   #170791

No tady ty příspěvky jsem si přečetl pozdě. :-D Ale to ještě opravím. ;-)

Jinak jsem se pustil do programování, ale ono ejhle. Něco je blbě. Tady je kód, ale na displeji se mi nic nezobrazí. Asi něco dělám špatně. A to jsem zkoušel už mooc věcí.

SPI mám nastavenou na rychlost 1MHz. Takže by to mělo fungovat. Ale kde je chyba, to nevím.

#include <avr/io.h>  
#include <stdio.h>
#include <util/delay.h>  
#include <avr/interrupt.h>  

#include "lcd.h"	//knihovna pro komunikaci s LCD 2004


// Mega16 Pinout
#define MOSI	4
#define MISO	6
#define SCLK	7
#define SS	4

char buffer[50];

unsigned int get_adc(unsigned char adata)
{
	static unsigned int temp=0;
	
	PORTB &= ~(1<<SS);					// SET CS do 0 (aktivovani ADC) 
										// zde by měla být krátká prodleva??
	SPDR = adata;					// vložit data do odesílací registru
	while(!(SPSR & (1<<SPIF)));			// Poslat 1 byte přes HW SPI a čeka na tx
	temp = SPDR;			         	// přijatá data nahraje do proměnné TEMP
	temp = temp << 8;				// posune proměnnou TEMP o 8 vlevo
	SPDR = adata;					// vloží data do odesílacího registru
	while(!(SPSR & (1<<SPIF)));			// Poslat 1 byte přes HW SPI a čeka na tx	
	temp |= SPDR;					// přijatá data nahraje do proměnné TEMP
	PORTB |= (1<<SS);				// nastavi CS do 1 a tim zakaze ADC 
	return temp;					// navratí hodnotu ADcka
}

void spim_init(void)
{
	// SET PORT B jako výstup 
	DDRB |= (1<<MOSI) | (1<<SCLK) | (1<<SS);
	// SET MISO jako vstup
	DDRB &= ~(1<<MISO); 
	// Povoleni SPI, SPI Master, SPI CLK XTAL/16, LSB First
	SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0);	        // CS HIGH protože SPI ADS je aktivní v         PORTB |= (1<<SS);	 
}

int main (void)
{
	lcd_init(LCD_DISP_ON);	//inicializace LCD
	
	static unsigned int adc_value=0;	// promenna AD prevodniku
	
	spim_init();						 	// Inicializace SPI jako MASTER
	adc_value = get_adc(0xFF);				// získání hodnoty z AD prevodniku


	lcd_gotoxy(0,1);
	printf(buffer,"%d",adc_value);
	lcd_puts(buffer);


	for(;;){}
}
Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
28. 1. 2013   #170775

#6 KIIV
No uvidíme jak daleko se dostanu. :-D Třeba se zadaří a pojede to hned. ;-)

Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
28. 1. 2013   #170773

#4 KIIV
Takže na mosi posílat data, abych mohl přijmout z toho ADčka. Tak to je taky dobré vědět. Dík moc

Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
28. 1. 2013   #170771

#2 KIIV
No s interním AD jsem už pracoval. Tak proč nevyzkoušet něco nového. ;-)

Ale teď zpět k tomu MAX187. Takže jak to jako připojit? To MOSI nevím kam připojit.

Jirka
Mikrokontroléry › Připojení AD převodníku k AV…
28. 1. 2013   #170769

Ahojte.

Chci se naučit pracovat s AD převodníkem, ale nemůžu přijít na to jak jej připojit k MCU. Mohl by mi někdo poradit, jestli to mám dobře?

Jedná se o MAX187 a atmegu16.

MAX187 komunikuje po SPI sběrnici.

A jde mi o to, jestli ty MAX187 signály SCLK, CS, DOUT můžu takto napojit na MCU (SCK, SS, MOSI), nebo jsetli ty signály musím připojit na jiné piny.

Tady jsem si sesmolil takový vlastní modulek. Poradí někdo? Děkuji

George
C / C++ › [C] Měření teploty pomocí DS…
12. 1. 2013   #170111

#5 George
Tak i tohle jsem už vyřešil. ;-) Kdyby náhodou.

sprintf (txstring,"%02d:%02d:%02d",hod,min,sek);
lcd_puts(txstring);
George
C / C++ › [C] Měření teploty pomocí DS…
12. 1. 2013   #170110

A abych nezakládal nové téma, chci se zeptat.

Dejme tomu, že mám hodnotu hodiny, které chci aby se na displeji zobrazovaly jako 00:00:00. Ale problém je  v tom, že mě se to zobrazí třeba takto: 12:2:24. Dá se to nějak odstranit, aby bylo zobrazeno 12:02:24??

sprintf (txstring,"%d:%d:%d",hod,min,sek);
lcd_puts(txstring);
George
C / C++ › [C] Měření teploty pomocí DS…
12. 1. 2013   #170098

No tak se nakonec podařilo. ;-)

if (DS18X20_read_decicelsius(&gSensorIDs[i-1][0],&decicelsius)==DS18X20_OK) 
	  				{
					sprintf(txstring,"%d", decicelsius);
					lcd_gotoxy(9,0);
					lcd_puts(txstring);
					 }

A musím jen doplnit, že výsledek decicelsius je nutné vydělit 10 ;-)

George
C / C++ › [C] Měření teploty pomocí DS…
12. 1. 2013   #170097

Tak jsem si s tím trošku pohrál a vyplodil jsem toto, protože temp je unit_16

if ( DS18X20_read_celsius( &gSensorIDs[i-1][0],&temp)== DS18X20_OK ) {
					a = temp/1000;
					pom = temp % 1000;
					b = pom/100;
					pom = pom % 100;
					c = pom / 10;
					pom = pom % 10;
					d = pom; 
					sprintf(txstring,"%d%d%d%d",a,b,c,d);
					lcd_gotoxy(10,0);
					lcd_puts(txstring);
				}

A zjistil jsem, že ono to číslo zdaleka nepřipomíná teplotu a až příliš se mění s teplotou např: 13107 pak 00007,.....

George
C / C++ › [C] Měření teploty pomocí DS…
12. 1. 2013   #170096

Velice se omlouvám, ta knihovna je špatná. Tato je ta dobrá.

/*********************************************************************************
Title:    DS18X20-Functions via One-Wire-Bus
Author:   Martin Thomas <eversmith@heizung-thomas.de>  
          http://www.siwawi.arubi.uni-kl.de/avr-projects
Software: avr-gcc 4.3.3 / avr-libc 1.6.7 (WinAVR 3/2010)
Hardware: any AVR - tested with ATmega16/ATmega32/ATmega324P and 3 DS18B20

Partly based on code from Peter Dannegger and others.

changelog:
20041124 - Extended measurements for DS18(S)20 contributed by Carsten Foss (CFO)
200502xx - function DS18X20_read_meas_single
20050310 - DS18x20 EEPROM functions (can be disabled to save flash-memory)
           (DS18X20_EEPROMSUPPORT in ds18x20.h)
20100625 - removed inner returns, added static function for read scratchpad
         . replaced full-celcius and fractbit method with decicelsius
           and maxres (degreeCelsius*10e-4) functions, renamed eeprom-functions,
           delay in recall_e2 replaced by timeout-handling
20100714 - ow_command_skip_last_recovery used for parasite-powerd devices so the
           strong pull-up can be enabled in time even with longer OW recovery times
20110209 - fix in DS18X20_format_from_maxres() by Marian Kulesza
**********************************************************************************/

#include <stdlib.h>
#include <stdint.h>

#include <avr/io.h>
#include <avr/pgmspace.h>

#include "ds18x20.h"
#include "onewire.h"
#include "crc8.h"

#if DS18X20_EEPROMSUPPORT
// for 10ms delay in copy scratchpad
#include <util/delay.h>
#endif /* DS18X20_EEPROMSUPPORT */

/*----------- start of "debug-functions" ---------------*/

/* functions for debugging-output - undef DS18X20_VERBOSE in .h
   if you run out of program-memory */
#include <string.h>

static int16_t DS18X20_raw_to_decicelsius( uint8_t fc, uint8_t sp[] );


#if DS18X20_VERBOSE
#define uart_puts_P_verbose(s__) uart_puts_P(s__)
#else
#define uart_puts_P_verbose(s__)
#endif


/*----------- end of "debug-functions" ---------------*/


/* find DS18X20 Sensors on 1-Wire-Bus
   input/ouput: diff is the result of the last rom-search
                *diff = OW_SEARCH_FIRST for first call
   output: id is the rom-code of the sensor found */
uint8_t DS18X20_find_sensor( uint8_t *diff, uint8_t id[] )
{
        uint8_t go;
        uint8_t ret;

        ret = DS18X20_OK;
        go = 1;
        do {
                *diff = ow_rom_search( *diff, &id[0] );
                if ( *diff == OW_PRESENCE_ERR || *diff == OW_DATA_ERR ||
                     *diff == OW_LAST_DEVICE ) {
                        go  = 0;
                        ret = DS18X20_ERROR;
                } else {
                        if ( id[0] == DS18B20_FAMILY_CODE || id[0] == DS18S20_FAMILY_CODE ||
                             id[0] == DS1822_FAMILY_CODE ) {
                                go = 0;
                        }
                }
        } while (go);

        return ret;
}

/* get power status of DS18x20
   input:   id = rom_code
   returns: DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE */
uint8_t DS18X20_get_power_status( uint8_t id[] )
{
        uint8_t pstat;

        ow_reset();
        ow_command( DS18X20_READ_POWER_SUPPLY, id );
        pstat = ow_bit_io( 1 );
        ow_reset();
        return ( pstat ) ? DS18X20_POWER_EXTERN : DS18X20_POWER_PARASITE;
}

/* start measurement (CONVERT_T) for all sensors if input id==NULL
   or for single sensor where id is the rom-code */
uint8_t DS18X20_start_meas( uint8_t with_power_extern, uint8_t id[])
{
        uint8_t ret;

        ow_reset();
        if( ow_input_pin_state() ) { // only send if bus is "idle" = high
                if ( with_power_extern != DS18X20_POWER_EXTERN ) {
                        ow_command_with_parasite_enable( DS18X20_CONVERT_T, id );
                        /* not longer needed: ow_parasite_enable(); */
                } else {
                        ow_command( DS18X20_CONVERT_T, id );
                }
                ret = DS18X20_OK;
        }
        else {
                ret = DS18X20_START_FAIL;
        }

        return ret;
}

// returns 1 if conversion is in progress, 0 if finished
// not available when parasite powered.
uint8_t DS18X20_conversion_in_progress(void)
{
        return ow_bit_io( 1 ) ? DS18X20_CONVERSION_DONE : DS18X20_CONVERTING;
}

static uint8_t read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n )
{
        uint8_t i;
        uint8_t ret;

        ow_command( DS18X20_READ, id );
        for ( i = 0; i < n; i++ ) {
                sp[i] = ow_byte_rd();
        }
        if ( crc8( &sp[0], DS18X20_SP_SIZE ) ) {
                ret = DS18X20_ERROR_CRC;
        } else {
                ret = DS18X20_OK;
        }

        return ret;
}


#if DS18X20_DECICELSIUS

/* convert scratchpad data to physical value in unit decicelsius */
static int16_t DS18X20_raw_to_decicelsius( uint8_t familycode, uint8_t sp[] )
{
        uint16_t measure;
        uint8_t  negative;
        int16_t  decicelsius;
        uint16_t fract;

        measure = sp[0] | (sp[1] << 8);
        //measure = 0xFF5E; // test -10.125
        //measure = 0xFE6F; // test -25.0625

        if( familycode == DS18S20_FAMILY_CODE ) {   // 9 -> 12 bit if 18S20
                /* Extended measurements for DS18S20 contributed by Carsten Foss */
                measure &= (uint16_t)0xfffe;   // Discard LSB, needed for later extended precicion calc
                measure <<= 3;                 // Convert to 12-bit, now degrees are in 1/16 degrees units
                measure += (16 - sp[6]) - 4;   // Add the compensation and remember to subtract 0.25 degree (4/16)
        }

        // check for negative
        if ( measure & 0x8000 )  {
                negative = 1;       // mark negative
                measure ^= 0xffff;  // convert to positive => (twos complement)++
                measure++;
        }
        else {
                negative = 0;
        }

        // clear undefined bits for DS18B20 != 12bit resolution
        if ( familycode == DS18B20_FAMILY_CODE || familycode == DS1822_FAMILY_CODE ) {
                switch( sp[DS18B20_CONF_REG] & DS18B20_RES_MASK ) {
                case DS18B20_9_BIT:
                        measure &= ~(DS18B20_9_BIT_UNDF);
                        break;
                case DS18B20_10_BIT:
                        measure &= ~(DS18B20_10_BIT_UNDF);
                        break;
                case DS18B20_11_BIT:
                        measure &= ~(DS18B20_11_BIT_UNDF);
                        break;
                default:
                        // 12 bit - all bits valid
                        break;
                }
        }

        decicelsius = (measure >> 4);
        decicelsius *= 10;

        // decicelsius += ((measure & 0x000F) * 640 + 512) / 1024;
        // 625/1000 = 640/1024
        fract = ( measure & 0x000F ) * 640;
        if ( !negative ) {
                fract += 512;
        }
        fract /= 1024;
        decicelsius += fract;

        if ( negative ) {
                decicelsius = -decicelsius;
        }

        if ( /* decicelsius == 850 || */ decicelsius < -550 || decicelsius > 1250 ) {
                return DS18X20_INVALID_DECICELSIUS;
        } else {
                return decicelsius;
        }
}

/* convert scratchpad data to physical value in unit celsius */
static double DS18X20_raw_to_celsius( uint8_t familycode, uint8_t sp[] )
{
        uint16_t measure;
        uint8_t  negative;
        int16_t  decicelsius;
        uint16_t fract;
        double celsius;

        measure = sp[0] | (sp[1] << 8);
        //measure = 0xFF5E; // test -10.125
        //measure = 0xFE6F; // test -25.0625

        if( familycode == DS18S20_FAMILY_CODE ) {   // 9 -> 12 bit if 18S20
                /* Extended measurements for DS18S20 contributed by Carsten Foss */
                measure &= (uint16_t)0xfffe;   // Discard LSB, needed for later extended precicion calc
                measure <<= 3;                 // Convert to 12-bit, now degrees are in 1/16 degrees units
                measure += (16 - sp[6]) - 4;   // Add the compensation and remember to subtract 0.25 degree (4/16)
        }

        // check for negative
        if ( measure & 0x8000 )  {
                negative = 1;       // mark negative
                measure ^= 0xffff;  // convert to positive => (twos complement)++
                measure++;
        }
        else {
                negative = 0;
        }

        // clear undefined bits for DS18B20 != 12bit resolution
        if ( familycode == DS18B20_FAMILY_CODE || familycode == DS1822_FAMILY_CODE ) {
                switch( sp[DS18B20_CONF_REG] & DS18B20_RES_MASK ) {
                case DS18B20_9_BIT:
                        measure &= ~(DS18B20_9_BIT_UNDF);
                        break;
                case DS18B20_10_BIT:
                        measure &= ~(DS18B20_10_BIT_UNDF);
                        break;
                case DS18B20_11_BIT:
                        measure &= ~(DS18B20_11_BIT_UNDF);
                        break;
                default:
                        // 12 bit - all bits valid
                        break;
                }
        }

        decicelsius = (measure >> 4);
        decicelsius *= 10;

        // decicelsius += ((measure & 0x000F) * 640 + 512) / 1024;
        // 625/1000 = 640/1024
        fract = ( measure & 0x000F ) * 640;
        if ( !negative ) {
                fract += 512;
        }
        fract /= 1024;
        decicelsius += fract;

        if ( negative ) {
                decicelsius = -decicelsius;
        }
       
        celsius = decicelsius;
        celsius = celsius/10;

        if ( /* decicelsius == 850 || */ decicelsius < -550 || decicelsius > 1250 ) {
                return 0;
        } else {
                return celsius;
        }
}


/* format decicelsius-value into string, itoa method inspired
   by code from Chris Takahashi for the MSP430 libc, BSD-license
   modifications mthomas: variable-types, fixed radix 10, use div(),
   insert decimal-point */
uint8_t DS18X20_format_from_decicelsius( int16_t decicelsius, char str[], uint8_t n)
{
        uint8_t sign = 0;
        char temp[7];
        int8_t temp_loc = 0;
        uint8_t str_loc = 0;
        div_t dt;
        uint8_t ret;

        // range from -550:-55.0°C to 1250:+125.0°C -> min. 6+1 chars
        if ( n >= (6+1) && decicelsius > -1000 && decicelsius < 10000 ) {

                if ( decicelsius < 0) {
                        sign = 1;
                        decicelsius = -decicelsius;
                }

                // construct a backward string of the number.
                do {
                        dt = div(decicelsius,10);
                        temp[temp_loc++] = dt.rem + '0';
                        decicelsius = dt.quot;
                } while ( decicelsius > 0 );

                if ( sign ) {
                        temp[temp_loc] = '-';
                } else {
                        ///temp_loc--;
                        temp_loc--;
                }

                // reverse the string.into the output
                while ( temp_loc >=0 ) {
                        str[str_loc++] = temp[(uint8_t)temp_loc--];
                        if ( temp_loc == 0 ) {
                                str[str_loc++] = DS18X20_DECIMAL_CHAR;
                        }
                }
                str[str_loc] = '\0';

                ret = DS18X20_OK;
        } else {
                ret = DS18X20_ERROR;
        }
       
        return ret;
}

/* reads temperature (scratchpad) of sensor with rom-code id
   output: decicelsius
   returns DS18X20_OK on success */
uint8_t DS18X20_read_decicelsius( uint8_t id[], int16_t *decicelsius )
{
        uint8_t sp[DS18X20_SP_SIZE];
        uint8_t ret;
       
        ow_reset();
        ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
        if ( ret == DS18X20_OK ) {
                *decicelsius = DS18X20_raw_to_decicelsius( id[0], sp );
        }
        return ret;
}

/* reads temperature (scratchpad) of sensor with rom-code id
   output: double
   returns DS18X20_OK on success */
uint8_t DS18X20_read_celsius( uint8_t id[], double *celsius )
{
        uint8_t sp[DS18X20_SP_SIZE];
        uint8_t ret;
       
        ow_reset();
        ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
        if ( ret == DS18X20_OK ) {
                *celsius = DS18X20_raw_to_celsius( id[0], sp );
        }
        return ret;
}

/* reads temperature (scratchpad) of sensor without id (single sensor)
   output: decicelsius
   returns DS18X20_OK on success */
uint8_t DS18X20_read_decicelsius_single( uint8_t familycode, int16_t *decicelsius )
{
        uint8_t sp[DS18X20_SP_SIZE];
        uint8_t ret;
       
        ret = read_scratchpad( NULL, sp, DS18X20_SP_SIZE );
        if ( ret == DS18X20_OK ) {
                *decicelsius = DS18X20_raw_to_decicelsius( familycode, sp );
        }
        return ret;
}

#endif /* DS18X20_DECICELSIUS */


#if DS18X20_MAX_RESOLUTION

static int32_t DS18X20_raw_to_maxres( uint8_t familycode, uint8_t sp[] )
{
        uint16_t measure;
        uint8_t  negative;
        int32_t  temperaturevalue;

        measure = sp[0] | (sp[1] << 8);
        //measure = 0xFF5E; // test -10.125
        //measure = 0xFE6F; // test -25.0625

        if( familycode == DS18S20_FAMILY_CODE ) {   // 9 -> 12 bit if 18S20
                /* Extended measurements for DS18S20 contributed by Carsten Foss */
                measure &= (uint16_t)0xfffe;   // Discard LSB, needed for later extended precicion calc
                measure <<= 3;                 // Convert to 12-bit, now degrees are in 1/16 degrees units
                measure += ( 16 - sp[6] ) - 4; // Add the compensation and remember to subtract 0.25 degree (4/16)
        }

        // check for negative
        if ( measure & 0x8000 )  {
                negative = 1;       // mark negative
                measure ^= 0xffff;  // convert to positive => (twos complement)++
                measure++;
        }
        else {
                negative = 0;
        }

        // clear undefined bits for DS18B20 != 12bit resolution
        if ( familycode == DS18B20_FAMILY_CODE || familycode == DS1822_FAMILY_CODE ) {
                switch( sp[DS18B20_CONF_REG] & DS18B20_RES_MASK ) {
                case DS18B20_9_BIT:
                        measure &= ~(DS18B20_9_BIT_UNDF);
                        break;
                case DS18B20_10_BIT:
                        measure &= ~(DS18B20_10_BIT_UNDF);
                        break;
                case DS18B20_11_BIT:
                        measure &= ~(DS18B20_11_BIT_UNDF);
                        break;
                default:
                        // 12 bit - all bits valid
                        break;
                }
        }

        temperaturevalue  = (measure >> 4);
        temperaturevalue *= 10000;
        temperaturevalue +=( measure & 0x000F ) * DS18X20_FRACCONV;

        if ( negative ) {
                temperaturevalue = -temperaturevalue;
        }

        return temperaturevalue;
}

uint8_t DS18X20_read_maxres( uint8_t id[], int32_t *temperaturevalue )
{
        uint8_t sp[DS18X20_SP_SIZE];
        uint8_t ret;
       
        ow_reset();
        ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
        if ( ret == DS18X20_OK ) {
                *temperaturevalue = DS18X20_raw_to_maxres( id[0], sp );
        }
        return ret;
}

uint8_t DS18X20_read_maxres_single( uint8_t familycode, int32_t *temperaturevalue )
{
        uint8_t sp[DS18X20_SP_SIZE];
        uint8_t ret;
       
        ret = read_scratchpad( NULL, sp, DS18X20_SP_SIZE );
        if ( ret == DS18X20_OK ) {
                *temperaturevalue = DS18X20_raw_to_maxres( familycode, sp );
        }
        return ret;

}

uint8_t DS18X20_format_from_maxres( int32_t temperaturevalue, char str[], uint8_t n)
{
        uint8_t sign = 0;
        char temp[10];
        int8_t temp_loc = 0;
        uint8_t str_loc = 0;
        ldiv_t ldt;
        uint8_t ret;

        // range from -550000:-55.0000°C to 1250000:+125.0000°C -> min. 9+1 chars
        if ( n >= (9+1) && temperaturevalue > -1000000L && temperaturevalue < 10000000L ) {

                if ( temperaturevalue < 0) {
                        sign = 1;
                        temperaturevalue = -temperaturevalue;
                }

                do {
                        ldt = ldiv( temperaturevalue, 10 );
                        temp[temp_loc++] = ldt.rem + '0';
                        temperaturevalue = ldt.quot;
                } while ( temperaturevalue > 0 );
               
                // mk 20110209
                if ((temp_loc < 4)&&(temp_loc > 1)) {
                        temp[temp_loc++] = '0';
                } // mk end

                if ( sign ) {
                        temp[temp_loc] = '-';
                }

                while ( temp_loc >= 0 ) {
                        str[str_loc++] = temp[(uint8_t)temp_loc--];
                        if ( temp_loc == 3 ) {
                                str[str_loc++] = DS18X20_DECIMAL_CHAR;
                        }
                }
                str[str_loc] = '\0';

                ret = DS18X20_OK;
        } else {
                ret = DS18X20_ERROR;
        }
       
        return ret;
}

#endif /* DS18X20_MAX_RESOLUTION */


#if DS18X20_EEPROMSUPPORT

uint8_t DS18X20_write_scratchpad( uint8_t id[],
        uint8_t th, uint8_t tl, uint8_t conf)
{
        uint8_t ret;

        ow_reset();
        if( ow_input_pin_state() ) { // only send if bus is "idle" = high
                ow_command( DS18X20_WRITE_SCRATCHPAD, id );
                ow_byte_wr( th );
                ow_byte_wr( tl );
                if ( id[0] == DS18B20_FAMILY_CODE || id[0] == DS1822_FAMILY_CODE ) {
                        ow_byte_wr( conf ); // config only available on DS18B20 and DS1822
                }
                ret = DS18X20_OK;
        }
        else {
                ret = DS18X20_ERROR;
        }

        return ret;
}

uint8_t DS18X20_read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n )
{
        uint8_t ret;

        ow_reset();
        if( ow_input_pin_state() ) { // only send if bus is "idle" = high
                ret = read_scratchpad( id, sp, n );
        }
        else {
                ret = DS18X20_ERROR;
        }

        return ret;
}

uint8_t DS18X20_scratchpad_to_eeprom( uint8_t with_power_extern,
        uint8_t id[] )
{
        uint8_t ret;

        ow_reset();
        if( ow_input_pin_state() ) { // only send if bus is "idle" = high
                if ( with_power_extern != DS18X20_POWER_EXTERN ) {
                        ow_command_with_parasite_enable( DS18X20_COPY_SCRATCHPAD, id );
                        /* not longer needed: ow_parasite_enable(); */
                } else {
                        ow_command( DS18X20_COPY_SCRATCHPAD, id );
                }
                _delay_ms(DS18X20_COPYSP_DELAY); // wait for 10 ms
                if ( with_power_extern != DS18X20_POWER_EXTERN ) {
                        ow_parasite_disable();
                }
                ret = DS18X20_OK;
        }
        else {
                ret = DS18X20_START_FAIL;
        }

        return ret;
}

uint8_t DS18X20_eeprom_to_scratchpad( uint8_t id[] )
{
        uint8_t ret;
        uint8_t retry_count=255;

        ow_reset();
        if( ow_input_pin_state() ) { // only send if bus is "idle" = high
                ow_command( DS18X20_RECALL_E2, id );
                while( retry_count-- && !( ow_bit_io( 1 ) ) ) {
                        ;
                }
                if ( retry_count ) {
                        ret = DS18X20_OK;
                } else {
                        ret = DS18X20_ERROR;
                }
        }
        else {
                ret = DS18X20_ERROR;
        }

        return ret;
}

#endif /* DS18X20_EEPROMSUPPORT */
George
C / C++ › [C] Měření teploty pomocí DS…
12. 1. 2013   #170095

Ahoj.

Našel jsem si knihovnu, pomocí které se snažím měřit teplotu. Nic těžkého, ale problém je, že se mi nedaří vyčíst teplotu z čidla. Zatím mám pouze jedno čidlo připojení k MCU atmega16, takt 16MHz.

Zde je knihovna DS18B20.c

#include <stdio.h>
 #include <avr/io.h>
 #include <util/delay.h>
 #include "config.h"
 #include "onewire.h"
 #include "ds18x21.h"
 #include "gps.h"

/****************************************************************************
 * Start measurement
 ****************************************************************************/
 void ds18x21_start_meas( unsigned int pin )
 {
   if( W1_IN & 1<< pin )
   {
     w1_byte_wr( 0xEE, pin );
   }
 }


/****************************************************************************
 * Display measurement result
 ****************************************************************************/
 double ds18x21_read_meas(unsigned int pin )
 {
   int t;
   int r;
   double c;
   double temperature;

   w1_reset(pin);
   w1_byte_wr( 0xAA, pin );                     // read temp
   t = w1_byte_rd(pin);                         // low byte
     
   w1_reset(pin);
   w1_byte_wr( 0xA0, pin);          // read remaining count
   r = w1_read(9, pin);

   w1_reset(pin);
   w1_byte_wr( 0x41, pin);          // load counter

   w1_reset(pin);
   w1_byte_wr( 0xA0, pin);          // read slope counter
   c = w1_read(9, pin);
   
   if ( t > 0x80 )
   {
      t = t-256;
   }

   temperature   = t - 0.5 + (( c - r ) / c);
     
   return temperature;

 }

 double ds18x21_get_meas(unsigned int pin, double * temp)
 {
                        int status;
                       
                        w1_reset(pin); // Put error cheking in
                        ds18x21_start_meas(pin);

                        for ( int i=0; i < 250; i++)
                        {
                                _delay_us (10000);
                               
                                w1_reset(pin);

                                w1_byte_wr( 0xAC, pin );
                                status = w1_byte_rd(pin);

                                // Temperature conversion finished ?
                                if ( status & 0x80)
                                {
                                   break;
                                }
                                       
                        }
                         
                         _delay_us (10000);

                        // read measurement value
                        *temp = ds18x21_read_meas(pin);
                       
                        return 1;
}              
 

Zde jsem si vytvořil cyklus pro ono měření:

	for ( i = nSensors; i > 0; i-- ) {	
		if ( DS18X20_start_meas( DS18X20_POWER_PARASITE, &gSensorIDs[i-1][0] ) == DS18X20_OK ) {                                     
			_delay_ms( DS18B20_TCONV_12BIT );
			sprintf (txstring,"T%d= ",(int) i);
			lcd_gotoxy(5,0);
			lcd_puts(txstring);
				if ( DS18X20_read_celsius( &gSensorIDs[i-1][0],&temp)== DS18X20_OK ) {
					sprintf(txstring,"%d",temp);
					lcd_gotoxy(10,0);
					lcd_puts(temp);
				}
		}
	}

No a když program přeložím, tak displej se zblázní. Může někdo poradit, co dělám špatně? Dík moc

Jirka
C / C++ › Výpočet max výško
10. 1. 2013   #170054

Zdravím všechny kdo čte tento příspěvek.

Mám malý problém. Mám za úkol simulovat teploměr na LCD pcd8544 (nokia 3310/5110). ;-)

Nic ohromnýho. Vše mi už funguje, ale nyní mám problém se zobrazení "grafiky".

Max teplota = 45°C což odpovídá Yaxis=6. Min teplota 0°C což zase odpovídá Yaxis=38.

A teĎ k problému. Když zadám aby vykreslil čáru o hodnotě teplota třeba = 20°C vše funguje. Ale když dám vykreslit 0°C, tak dojde k tomu, že vykreslím čáru kde nemám, protože nevím jak to přepočítat.

U mě to je takto: teplota = Yaxis. Jak to přepočítat, a ještě jeden problémek, nemůžu počítat s desetinnýma číslama, protože pracuju s Atmegou16.

Vím, napsal jsem to tak složitě, ale nevím jak nejlépe problém popsat. PLS poraďte.

Bumbaj
C / C++ › [C] Zobrazení proměnné na LC…
9. 1. 2013   #170030

No tak nakonec se přeci jen podařilo. ;-)

sprintf(buffer, "%i", teplota,teplota%10);
LcdStr(FONT_1X,(unsigned char*)buffer);
Bumbaj
C / C++ › [C] Zobrazení proměnné na LC…
9. 1. 2013   #170026

Ahojte. Dneska si jenom tak hraju s LCD od nokie 5110. Připojil jsem ji k MCU a něco si na něm nakreslil, napsal. Ale pak jsem si řekl, že bych se na něm mohl zobrazit teplotu. A zde je ten problém. Nějak nedokážu na tento displej zobrazi proměnnou. :-D

Tak dejme tomu, že mám proměnnou teplota, která je typu char. A teď jak pomocí těchto proměnných, které mám k dispozici, zobrazím onu teplotu v číslech na tom LCD? Stačí přesnost na celé číslo "00". Co myslíte, půjde to?

byte LcdChr        ( LcdFontSize size, byte ch );
byte LcdStr        ( LcdFontSize size, byte dataArray[] );
byte LcdFStr       ( LcdFontSize size, const byte *dataPtr )
Rotoped
C / C++ › [C] přerušení timeru0 v reži…
8. 11. 2012   #166218

#3 reciproke
Jsem to tupec. :-D Celou dobu na to hledím.

1ms/4us =250

Jsem si akorát nějak neuvědomil předpony (1e-3/4e-6). :-D A to s tím potom můžu experimentovat do bůh ví kdy.

Dík moc

Rotoped
C / C++ › [C] přerušení timeru0 v reži…
8. 11. 2012   #166209

#1 Rotoped
a omlouvám se, kód jsem trošku špatně napsal.

//zde je nastaveni TIMERU0 z main

TCCR0 |= (1<<WGM01)|(1<<CS01)|(1<<CS00); 	//CTC mode, preddelicka 64 (4us)
OCR0=50;
TIMSK  |= (1 << OCIE0);




//zde je interrupt smyčka
ISR(TIMER0_COMP_vect){ 		//přerušení od čítače časovače 0
	
}
Rotoped
C / C++ › [C] přerušení timeru0 v reži…
8. 11. 2012   #166207

Hojte. PLS mám malý problém. Nějak se nemůžu dopočítat.

Nastavil jsem si TIMER0 a modu CTC.

Krystal mám 16MHz.

Takže jsem nastavil děličku na 64 z toho vyplývá, že přetečení nastane vždy jednou za 4us, [1/(16/64)=4us] pokud to říkám dobře. A já teď nemůžu zjistit, na kolik musím nastavit OCR0, aby bylo 100us. Nebo jestli by to šlo, tak aby 1ms.

Tak se chci zeptat, nevíte nějaký vzorec, podle kterého to spočítám? Děkuji

ISR(TIMER0_COMP_vect){ 		//přerušení od čítače časovače 0
	
}
TCCR0 |= (1<<WGM01)|(1<<CS01)|(1<<CS00); 	//CTC mode, preddelicka 64 (4us)
OCR0=25;
TIMSK  |= (1 << OCIE0);
Jirka
Mikrokontroléry › Ošetření tlačítka
7. 11. 2012   #166057

Ahojte.Tak jsem to zkoumal a je to opravdu pravda. Jenom číňani to zkouší jako já. :-D Takže jsem to trošku ošetřil HW (kondík) a jinak jsem použil časovač a ejhle už to šlape jak hodinky. Pro jistotu jsem tlačítko ošetřil i SW.

unsigned char 	tlac_prodleva,tlac_present;
ISR (TIMER1_OVF_vect){  	//tlacitko rotacniho enkoderu + osetreni zakmitu

TCNT1 = 64911;	//preteceni

	if((PIND & (1 << PD3))){
        if(tlac_prodleva<20) 
        	tlac_prodleva++;
        if(tlac_prodleva==19) 
            tlac_present=1;   
        }
        else{
        if(tlac_prodleva==20){
			flag++;
			encoder=0;
        	}        
        tlac_prodleva=0;
        }
}
Jirka
Mikrokontroléry › Ošetření tlačítka
6. 11. 2012   #165990

Takže takto by to mohlo být?

ISR(INT1_vect)		//tlačitko
    {  
	cli();
		_ms_delay(1);
	pricti++;
	sei();
    }

neboli, pokaždé když stisknu tlačítko, tak se hodnota pricti strikně zvýší o 1.


Jirka
Mikrokontroléry › Ošetření tlačítka
6. 11. 2012   #165983

Ahojte.

Myslíte, že by se našel někdo, kdo by mi pomohl? Stavím si časovač, a připojil jsem si tlačítko na přerušení INT1. A mě by zajímalo, jestli by zde šlo ošetřit to tlačítko proti zákmitům. A jestli jo, jak to provedu?? Klidně přidám svůj kód, ale myslím si, že to není potřeba. Děkuji za jakoukoli radu

Jirka
C / C++ › 7segmentovka (zobrazování ji…
30. 9. 2012   #163973

Tak jsem se s tím popral po svém. :-D Pro ty, kdo by někdy řešil obdobný problém, tak tady je řešení. Sice nevím jestli je úplně OK, ale funguje.

//pole DAT
const char textdata[] PROGMEM=
{
0b11000000,//0
0b11111001,//1
0b10100100,//2
0b10110000,//3
0b10011001,//4
0b10010010,//5
0b10000010,//6
0b11111000,//7
0b10000000,//8
0b10010000,//9
0b10011100,//°
0b11000110,//C
};

//pomocí podmínky (potreba) je zobrazováno 'xx°C'
char potreba=0;
void zapis_na7segment()		//zobrazovač na 4x7-segmentovce
{
	if (potreba==0)
	{
	des_hodin=pgm_read_byte(&textdata[des_hodin]);
	zapisBYTU74595(des_hodin);
	jed_hodin=pgm_read_byte(&textdata[jed_hodin]);
	zapisBYTU74595(jed_hodin);
	des_minut=pgm_read_byte(&textdata[des_minut]);
	zapisBYTU74595(des_minut);
	jed_minut=pgm_read_byte(&textdata[jed_minut]);
	zapisBYTU74595(jed_minut);
	shift_register_hi;
	_delay_ms(10);
	shift_register_lo;
	}
		else
			{
			des_hodin=pgm_read_byte(&textdata[des_teplota]);
			zapisBYTU74595(des_hodin);
			jed_hodin=pgm_read_byte(&textdata[jed_teplota]);
			zapisBYTU74595(jed_hodin);
			des_minut=pgm_read_byte(&textdata[10]);
			zapisBYTU74595(des_minut);
			jed_minut=pgm_read_byte(&textdata[11]);
			zapisBYTU74595(jed_minut);
			shift_register_hi;
			_delay_ms(10);
			shift_register_lo;
			}

}

Jirka
C / C++ › 7segmentovka (zobrazování ji…
30. 9. 2012   #163965

Dobrý den,

řeším problém se 4 sedmisegmentovkama. Na internetu jsem našel program, který jsem si upravil ke své podobě a na kterém se učím.

A můj problém je takovýto:

chtěl bych, aby 7 segmentovka nezobrazovala pouze čísla, ale i jiné symboly.

Třeba '°C', nebo si zobrazit jen jeden segment. Myslíte, že to půjde? Tady přikládám můj program:

//#define F_CPU 8000000L
#include "util/delay.h"
#include "stdlib.h"
#include "avr/io.h"
#include "avr/pgmspace.h"
#include "avr/interrupt.h"

#define shift_register_hi	PORTD|=(1<<3)
#define shift_register_lo	PORTD&=~(1<<3)

#define clock_register_hi	PORTD|=(1<<1)
#define clock_register_lo	PORTD&=~(1<<1)

#define serial_register_hi		PORTD|=(1<<0)
#define serial_register_lo		PORTD&=~(1<<0)

const char textdata[] PROGMEM=
{
0b11000000,//0
0b11111001,//1
0b10100100,//2
0b10110000,//3
0b10011001,//4
0b10010010,//5
0b10000010,//6
0b11111000,//7
0b10000000,//8
0b10010000,//9

0b10011100,//°
0b11000110,//C
};
//====================================================================
unsigned char jed_hodin,des_hodin,jed_minut,des_minut,minuty,hodiny,sekundy;	//jednotky hodin, desítky hodin, jednotky minut, desítky minut 
																				//minuty, hodiny, druhý
//--------------------------INICIALIZACE---------------------------------------
void init_devices()		//inicializace 74HC595
{
	DDRD |= (1 << PD0);		//nastaveni bitu PD0 jako vystupni
	DDRD |= (1 << PD1);		//nastaveni bitu PD1 jako vystupni
	DDRD |= (1 << PD3);		//nastaveni bitu PD3 jako vystupni

	serial_register_lo;		
	shift_register_lo;
	clock_register_lo;
}
//------------------------KONEC INICIALIZACE---------------------------------

void clock_74595()		//hodinový pulz 74HC595
{
	clock_register_hi;
	clock_register_lo;
}

void kirimbyte74595(unsigned char data_led)		//zápis BYTE
{	
	if(bit_is_set(data_led,7)) serial_register_hi;else serial_register_lo;
	clock_74595();
	if(bit_is_set(data_led,6)) serial_register_hi;else serial_register_lo;
	clock_74595();
	if(bit_is_set(data_led,5)) serial_register_hi;else serial_register_lo;
	clock_74595();
	if(bit_is_set(data_led,4)) serial_register_hi;else serial_register_lo;
	clock_74595();
	if(bit_is_set(data_led,3)) serial_register_hi;else serial_register_lo;
	clock_74595();
	if(bit_is_set(data_led,2)) serial_register_hi;else serial_register_lo;
	clock_74595();
	if(bit_is_set(data_led,1)) serial_register_hi;else serial_register_lo;
	clock_74595();
	if(bit_is_set(data_led,0)) serial_register_hi;else serial_register_lo;
	clock_74595();
}

void zapis_na7segment()		//zobrazovač na 4x7-segmentovce
{
	des_hodin=pgm_read_byte(&textdata[des_hodin]);
	kirimbyte74595(des_hodin);
	jed_hodin=pgm_read_byte(&textdata[jed_hodin]);
	kirimbyte74595(jed_hodin);
	des_minut=pgm_read_byte(&textdata[des_minut]);
	kirimbyte74595(des_minut);
	jed_minut=pgm_read_byte(&textdata[jed_minut]);
	kirimbyte74595(jed_minut);
	shift_register_hi;
	_delay_ms(10);
	shift_register_lo;
}

void prevod()	//prevod cisla
{
	des_hodin=hodiny/10;	//destíky hodiny
	jed_hodin=hodiny%10;	//jednotky hodiny
	des_minut=minuty/10;	//desítky minut
	jed_minut=minuty%10;	//jednotky minut
}

ISR (TIMER1_COMPA_vect)
{
	TCNT1 = 0;
	
}

//------------------------------hlavni smycka------------------------------------
int main()
{
	minuty=0;
	hodiny=0;
	sekundy=0;
	
	init_devices();

	TCCR1B |= (1<< CS12);
	TIMSK |= (1<< OCIE1A);
	OCR1A=31249;
	sei();	

	for(;;)
	{
		prevod();	//fce prevod prevede cislo na jednotky a desitky
		zapis_na7segment();
	}
	
}

Budu rád za jakoukoli odpověď. Děkuji

Tonda
Mikrokontroléry › čas za který nastane přeruše…
30. 9. 2012   #163959

Ahojte. Myslíte, že by se tu našla dobrá duše, která by mi poradila? Potřeboval bych zjistit, za jakou dobu nastane přerušení, když mám krystal 8MHz a nastavení takovéto:

	TCCR1B |= (1<< CS12);
	TIMSK |= (1<< OCIE1A);
	OCR1A=65224;

podle mých výpočtů cca každých 10ms. Je to OK? Děkuji

Kuzzi
C / C++ › délka stisku tlačítka v C pr…
23. 9. 2012   #163658

#4 KIIV
jjasné. Z tohoto to dám už asi do kupy. Dík moc za pomoc

Kuzzi
C / C++ › délka stisku tlačítka v C pr…
23. 9. 2012   #163652

#2 KIIV
No to je mi jasné, že musím v přerušení nějak načítat ten čas. Ale právě toto nějak nevím jak udělat. Nenašel by se nějaký příkládek?

Kuzzi
C / C++ › délka stisku tlačítka v C pr…
23. 9. 2012   #163646

Ahojte. prosím měl bych jeden dotaz. Snažím se udělat program, který by reagoval na stisk tlačítka. A to tak, že bych rozlišoval dlouhý a krátký stisk. Ale nějak nevím jak na to. Mohl by mi někdo poradit?

jirkaj4
Mikrokontroléry › Změna portu v programu??
21. 9. 2012   #163573

#1 jirkaj4
Tak jsem tady z5. Našel jsem na internetu zajímavý příklad programu, ale nějak nemůžu přijít, jak ty jednotlivé funkce použít. Může mi někdo poradit? Třeba jak na tu sběrnici (I2C) poslat nějaký bajt? Nebo jak jí říct, že čtu?

http://codinglab.blogspot.cz/…banging.html

Mikrokontroléry › Změna portu v programu??
20. 9. 2012   #163497

 

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý