Fórum témák
- • Kapcsolási rajzot keresek
- • Gitár Pickup
- • Villanyszerelés
- • Klíma beszerelése, fűtés-hűtés házilag
- • Aggregátor feszültség szabályzó
- • Ráz a kültéri medence vize
- • Elektromos kerékpár, robogó házilag
- • Klíma szervizelés, javítás
- • Felajánlás, azaz ingyen elvihető
- • Kondenzátor feltöltés
- • Folyamatábrás mikrokontroller programozás Flowcode-dal
- • Vásárlás, hol kapható?
- • Számítógép hiba, de mi a probléma?
- • Rádió építés a kezdetektől a világvevőig
- • Westen 240 Fi gázkazán hiba
- • Mikrohullámú sütő javítás, magnetron csere, stb.
- • VF3 - 6 végerősítő
- • Villanypásztor
- • Mosógép vezérlők és általános problémáik
- • Villanymotor
- • Quad 405-ös erősítő tapasztalatok és hibák
- • LM1875, LM3875, LM3886, stb. TI végerősítők
- • RFID Miértek és hogyanok
- • Li-Po - Li-ion akkumulátor és töltője
- • Audiofil, High End Audio
- • Alternativ HE találkozó(k)
- • PLC alapismeretek
- • PIC - Miértek, hogyanok haladóknak
- • Páratartalom érzékelő
- • Kondenzátor
- • Inverteres hegesztőtrafó
- • Erősítő mindig és mindig
- • TV hiba, mi a megoldás?
- • Elektromos fűnyíró probléma
- • Li-Ion saját akkucsomag készítése
- • Ki hol gyártatja a NYÁK-ot ?
- • Flip-Flop? Bistabil? Buffer?
- • Egyfázisú motor forgásirány váltása mágneskapcsolóval
- • Indukciós főzőlap javítása
- • Espressif mikrokontrollerek
- • Hörmann kapuk
- • Műveleti erősítő
- • Kombikazán működési hiba
- • Codefon kaputelefon
- • Autóelektronika
- • Porszívó javítás
- • Rádióamatőrök topikja
- • Muzeális készülékek-alkatrészek restaurálása
- • Analóg oszcilloszkóp javítása
- • Elektromos távirányítós kapunyitó
- • Érdekességek
- • Sütő javítás
- • DVB-T - Földfelszíni digitális problémák
- • Frekvencia - feszültség átalakító
- • Mosogatógép hiba
» Több friss téma
|
Ezen az oldalon mindjárt az első mintapélda is tartalmazza az sw_uart_outdec() függvényt, amelyet könnyen át lehet írni LCD kijelzésre ( a függvény nevét, meg az egy karaktert kiíró sw_uart_putc() hívásokat kell megváltoztatni benne.
Sziasztok.
Egy kicsit bizonytalan vagyok. Összehoztam egy egyszerű fordulatszámmérőt, de nem vagyok benne biztos, hogy jól számoltam-e.
A hardverről csak annyit, hogy egy CD-ből kioperált motorra ragasztottam egy mágnest, és elé raktam egy HALL szenzort ( TLE4905), és a jelét egy ellenállás osztón keresztül kapja meg a g2231 capture modulja. (természetesen 100nF-al szűrve)
Beállítottam a motor fordulatszámát ~6000-re, de szerintem nem forog annyit a motor. Hogy tudnám azt leellenőrizni, hogy jó-e a mért értékem?
Prog:
while(1){
if(uart){
_DINT();
P1OUT ^= BIT0;
long captured=0, cap_val=0;
unsigned int captured_rpm=0, captured_hz=0;
for(char j=1; j<6;j++){
cap_val += capture_buffer[j];
}
captured = cap_val / 5;
captured_hz = frequency / captured;
captured_rpm = (captured_hz<<2)+(captured_hz<<1);
sw_uart_puts("\r\nFrequency = ");
sw_uart_outdec(captured_hz,0);
sw_uart_puts(" Hz Fordulat = ");
sw_uart_outdec(captured_rpm,0);
sw_uart_puts(" RPM");
}
__low_power_mode_0();
}
}
#pragma vector=TIMERA1_VECTOR
__interrupt void TimerA1(void){
new_capture = TACCR1;
capture_buffer[count++] = new_capture - old_capture;
if (count==6){
count=0;
uart=1;
TACCTL1 &= ~CCIFG;
__low_power_mode_off_on_exit();
}
old_capture = new_capture;
TACCTL1 &= ~CCIFG;
}
A hozzászólás módosítva: Márc 12, 2013
Valóban!
Köszönöm. Egy másik MCU-val (g2252) előállítottam, szkóp és freki mérő szerint pontosan 500Hz-et. Ezt mérem a g2231-el, a lenti programmal, és a kiírt eredmény "1974". Nem 2000 kéne legyen?
Kiíró és számoló rutin:
while(1){
if(uart){
_DINT();
P1OUT ^= BIT0;
captured=0;
for(char j=1; j<6;j++){
captured += capture_buffer[j];
}
captured /=5;
sw_uart_outdec(captured,0);
sw_uart_puts("\r\n");
}
__low_power_mode_0();
}
A program elején (#define LCM_PIN_RS BIT0......) található az LCD bekötése:
LCD RS=P1.0, LCD EN=P1.1 stb.
Ezek után, az "int main(){" részben vedd ki kommentből az inicializálást, és a képernyő törlést, állítsd be a kurzor pozíciót, és az UART küldés után, elé, rakd be a HD44780_outdec..... sort.
Az MSP430G2553 hardveres UART full duplex használatához portoltam a PICula projektemben kidolgozott szoftveres bufferelésű (gyűrű táras) és interruptos kezelésű uart_putc(), uart_getc() függvényeket.
Használata: A projektekbe fel kell venni a hw_uart_buf.c állományt, s a fenti függvényket használó fordítási egységekbe (pl. főprogram) be kell csatolni hw_uart_buf.h fejléc állományt.
Egy kis bónusz: IAR EW esetén ha felüldefiniáljuk a putchar() függvényt, akkor a printf() függvény is használható a kiírásra. Ugye, milyen egyszerű? Mintapélda:
#include <stdint.h>
#include <stdio.h>
#include "hw_uart_buf.h"
int putchar(int outChar) {
uart_putc((uint8_t)outChar);
return outChar;
}
char c;
int main( void ) {
WDTCTL = WDTPW + WDTHOLD; //Letiltjuk a watchdog időzítőt
DCOCTL = CALDCO_1MHZ; //DCO beállítása a gyárilag kalibrált
BCSCTL1 = CALBC1_1MHZ; //1 MHz-es frekvenciára
uart_init(BPS_9600);
printf("NLIsten hozott a Launchpad projekthez!");
printf("hello_print program (hw_uart_buf)NL");
while (1) {
c=uart_getc();
printf("Vett karakter: %c = %dNL",c,c);
}
}
Ha a printf() függvényt nem akarjuk használni, akkor a kiíratást a hw_uart_buf.c állományban definiált (itt már többször bemutatott) függvények segitségével is végezhetjük. Például így:
#include <stdint.h>
#include "hw_uart_buf.h"
char c;
int main( void ) {
WDTCTL = WDTPW + WDTHOLD; //Letiltjuk a watchdog időzítőt
DCOCTL = CALDCO_1MHZ; //DCO beállítása a gyárilag kalibrált
BCSCTL1 = CALBC1_1MHZ; //1 MHz-es frekvenciára
uart_init(BPS_9600);
uart_puts("NLIsten hozott a Launchpad projekthez!NL");
uart_puts("hello_int program (hw_uart_buf)NL");
while (1) {
c=uart_getc();
uart_puts("Vett karakter: ");
uart_putc(c);
uart_puts(" = ");
uart_outdec((int32_t)c,0);
uart_puts(" NL");
}
}
Megjegyzések:
1. Sajnos, a fórummotor nem engedi berakni a newline karaktereket, ezért NL-lel helyettesítettem!
2. Az IAR EW projekt opcióknál célszerű a printf függvény használatát "Auto"-ra állítani, hogy fölösleges formátumok kezelésével ne tömje tele a programunkat.
HIBAIGAZÍTÁS:
Hibát találtam a mintaprogramjaimban használt számkiírató eljárás működésében: Ha a kiírandó érték a 10-zel történő osztásoknál "elfogy", mielőtt a tizedespontot kiírnánk, akkor a tizedes pont nem kerül kiírásra, s így hamis lesz a kiírt érték. Például 0.075V helyett 75V eredményt kapunk!
Javítás: A hiba orvoslására figyelnünk kell azt is, hogy legalább annyi számjegyet mindenképp írassunk ki, mint ahány tizedesjegyet ki akartunk íratni.
Példa: Az alábbi példában legalább egy számjegyet kiíratunk a tizedespont előtt, tehát az értéktelen nulla egész is kiírásra kerül (pl. .735 helyett 0.735).
/**------------------------------------------------------------
* Decimális kiíratás adott számú tizedesjegyre.
*-------------------------------------------------------------
* data - a kiírandó szám (előjelesen)
* ndigits - a kiírandó tizedesek száma
*/
void sw_uart_outdec(int32_t data, uint8_t ndigits) {
static char sign, s[12];
uint8_t i;
i=0; sign='+';
if(data<0) { sign='-'; data = -data;}
do {
s[i]=data%10 + '0';
data=data/10;
i++;
if(i==ndigits) {s[i]='.'; i++;}
} while(data > 0 || i < ndigits+2);
sw_uart_putc(sign);
do {
sw_uart_putc(s[--i]);
} while(i);
}
További módosítási lehetőség: A sign='+'; utasításban a pluszjel helyett szóközt is írhatunk a fölösleges előjel kiíratásának elkerülésére. A hozzászólás módosítva: Okt 1, 2012
Nézz szét a topikban (" outdec" a varázsszó), találsz rá megoldást! A hőmérsékletet tizedfok egységekre konvertáld, s a kiíratásnál jelezzük, hogy egy tizedesre kérjük a kiíratást.
Ugyanezt a módszert használom soros porti kiíratásnál is. Bővebben: link.
Nem szép dolog, hogy az átlagolást nem kettő hatványa szerint csinálod! (16 vagy 32 minta esetén az osztás jobbra léptetéssel megoldható).
A negatív számokat én a kiíratásnál ellenőrzöm, az if(data<0) { sign='-'; data = -data;} sorban.
Unsigned változó esetén így kellene: if((a=b)>32767) a= 65536-a; (Itt a az unsigned16 b pedig az előjeles változó)
/**------------------------------------------------------------
* Decimális kiíratás adott számú tizedesjegyre.
*-------------------------------------------------------------
* data - a kiírandó előjeles szám (int32_t)
* ndigits - a kiírandó tizedesek száma (uint8_t)
*/
void sw_uart_outdec(int32_t data, uint8_t ndigits) {
static char sign, s[12];
int8_t i;
i=0; sign=' ';
if(data<0) { sign='-'; data = -data;}
do {
s[i]=data%10 + '0';
data=data/10;
i++;
if(i==ndigits) {s[i]='.'; i++;}
} while(data>0);
sw_uart_putc(sign);
do {
sw_uart_putc(s[--i]);
} while(i);
}
A te kódrészleted számomra értelmezhetetlen, mert a változó típusokat nem adtad meg benne.
A belső hőmérő használata gyári kalibrációs adatokkal
Az MSP430G2452 és MSP430G2553 mikrovezérlők az ADC-hez is tartalmaznak gyári kalibrációs adatokat. A fejléc állományokban azonban nincs definiálva hozzájuk szimbolikus név, ezért vagy a programunkba, vagy a fejléc állományokba helyezzük el az alábbi sorokat:
/* ADC10 Calibration Data - added by I. Cserny */
__no_init unsigned __READ int CAL_ADC_25T85 @ 0x10EA;
__no_init unsigned __READ int CAL_ADC_25T30 @ 0x10E8;
__no_init unsigned __READ int CAL_ADC_25VREF_FACTOR @ 0x10E6;
__no_init unsigned __READ int CAL_ADC_15T85 @ 0x10E4;
__no_init unsigned __READ int CAL_ADC_15T30 @ 0x10E2;
__no_init unsigned __READ int CAL_ADC_15VREF_FACTOR @ 0x10E0;
__no_init unsigned __READ int CAL_ADC_OFFSET @ 0x10DE;
__no_init unsigned __READ int CAL_ADC_GAIN_FACTOR @ 0x10DC;
A definíciókból kihagytam a volatile módosítót, feltételezve, hogy programfutás közben úgysem változnak ezek az adatok...
A CAL_ADC_GAIN_FACTOR és az CAL_ADC_OFFSET elvileg az ADC-ből kiolvasott eredmény korrekciójához kell. Nálam ezek annyira közel esnek 1-hez és 0-hoz, hogy nem érdemes veszkődni vele.
A mellékelt programban a 2,5 V-os belső referenciát használjuk, ezért a belső hőmérő kiolvasott értékének átszámításához a 2,5 V-os referenciával 30 és 85 fokon mért értékeket használjuk a C-fokra történő átszámításhoz, lineáris összefüggést feltételezve:
TCelsius = 55 * (ADC10MEM - CAL_ADC_25T30)/(CAL_ADC_25T85 - CAL_ADC_25T30) + 30;
Vagyis a 30 fokhoz viszonyítunk, s az 55 fokos különbségnél (85 C - 30 C ) kapott gyári értékekből határozzuk meg a meredekséget is.
A tapasztalat szerint az így kiszámolt érték kb. 3 fokkal fölé lőtt a szobahőmérőnek, ezért a továbbiakban 30 fok helyett csak 27 fokot használok a képletben. Ha tizedfokokat is ki akarunk íratni (bár sok értelme nincs), akkor a fenti képletben 10-zel kell szorozni a konstansokat (tehát 55 helyett 550, 30 helyett 300, vagy 27 helyett 270).
A mellékelt mintaprogramban a P1.5 bemenetre kapcsolt feszültséget (0 - 2,5 V) is mérjük, valamint a 11. csatornában a VDD/2 feszültséget is. Utóbbiból meghatározhatjuk a tápfeszültséget, felhasználva, hogy most független referenciánk van. A feszültségeket millivoltokban célszerű kiszámolni.
Ha takarékoskodni akarunk a mérési idővel, akkor nem túl nagy csalás, ha 1023 helyett 1024-gyel osztunk (hogy léptetéssel megoldható legyen), de a programban nem éltem ezzel a lehetőséggel.
A kiírást a korábban már ismertetett outdec() függvénnyel végezzük, ahol második paraméterként a levágandó tizedesjegyek számát kell megadni (hőmérésnél 1, mV-ban kiszámolt feszültségnél pedig 3).
A program érdekessége, hogy nem használunk benne float változót, s a kiíratáshoz a korábban bemutatott egyirányú szoftveres UART kezelést használjuk.
A mellékelt képen P1.5 összevissza kóvályog, mert csak a felszedett zajt mérte...
Idézet: „Van egy LCD kijelzőm amire kiíratom a hőmérsékletet , de csak egész számként megy, ezt szeretném mondjuk 2 tizedesig vagy egyig növelni.” Akkor jól félreértettem az előző kérdést! 
A mostanira ez a javaslatom:
IntDegC = ((temp - 673) * 423) / 1024;
lcd_write(0xC7,0);
outdec(IntDegC,0);
A fenti sorok helyett ezzel próbálkoznék:
IntDegC = ((temp - 673) * 4230) / 1024;
lcd_write(0xC7,0);
outdec(IntDegC,1);
Pont ezt linkeltem be, de ha jobban megnézed csak element14-től lehet rendelni, viszont csak a szingapuri központból ahonnan csak Kina, Taiwan , etc helyekre lehet rendelni.
Én is TI-s Touch Pad KIt-re gondolok, nem másra.Ők a gyártók velük beszélek közvetlenül.
Ezért írtam ha valaki szeretne ilyet akkor szóljon, mert rajta vagyok az ügyön.
Más:
Icserny köszönöm a válaszod, lehet nem jól írtam le h mit akarok  Van egy LCD kijelzőm amire kiíratom a hőmérsékletet , de csak egész számként megy, ezt szeretném mondjuk 2 tizedesig vagy egyig növelni.
Isten ments az msp430->PC kommunikációtol.
Forrás:
#include "io430.h"
#include "stdint.h"
#include "intrinsics.h"
/* LCD port és vezérlo" bitek megadása */
#define LCD_PORT P1OUT
#define LCD_PORT_DIR P1DIR
#define LCD_MASK BIT7+BIT6+BIT5+BIT4
#define LCD_RS P2OUT_bit.P6
#define LCD_RS_DIR P2DIR_bit.P6
#define LCD_E P2OUT_bit.P7
#define LCD_E_DIR P2DIR_bit.P7
/**-----------------------------------------------
* Inline függvény, amely egy regiszter valamelyik
* bitcsoportját atomi mu"velettel módosítja
*-----------------------------------------------
* param reg a módosítandó regiszter neve
* param val a beírandó érték (helyiérték-helyesen!)
* param mask a módosítandó bitcsoportot kijelölo" maszk
*/
#define ChangeBits(reg,val,mask) reg^=((reg^val)&mask)
/**----------------------------------------------
* Késlelteto" eljárás (1 - 65535 ms)
*-----------------------------------------------
* param delay a késleltetés ms egységben megadva
*/
void delay_ms(uint16_t delay) {
uint16_t i;
for(i=0; i<delay; i++) {
__delay_cycles(1000);
}
}
/**----------------------------------------------
* LCD Enable bemenet pulzálása
*-----------------------------------------------
*/
void lcd_toggle_E() {
LCD_E = 1;
__delay_cycles(500);
LCD_E = 0;
__delay_cycles(500);
}
/**----------------------------------------------
* Egy bájt kiküldése az LCD vezérlo"jének
*-----------------------------------------------
* param val a kiírandó érték
* param cmd regiszterválasztó bit (0: parancs, 1: adat)
*/
void lcd_write(uint8_t val, uint8_t cmd) {
LCD_RS = cmd;
ChangeBits(LCD_PORT,(val&0xF0),LCD_MASK);
lcd_toggle_E();
ChangeBits(LCD_PORT,((val&0x0F)<<4),LCD_MASK);
lcd_toggle_E();
__delay_cycles(1000);
}
/*-----------------------------------------------
* LCD kijelzo" inicializálása
*-----------------------------------------------
*/
void lcd_init (void){
//-- Az LCD port inicializálása
ChangeBits(LCD_PORT,0x00,LCD_MASK);
ChangeBits(LCD_PORT_DIR,LCD_MASK,LCD_MASK);
P2SEL = 0;
LCD_RS = 0;
LCD_RS_DIR = 1;
LCD_E = 0;
LCD_E_DIR = 1;
delay_ms(100); //40ms várakozás bekapcsolás után
//-- Az LCD vezérlo"jének inicializálása:
//-- 1. szoftveres LCD reset: 0x30 (8-bites mód) kiírása háromszor
//-- 2. 4-bites üzemmód beállítása
//-- 3. Képernyo"törlés, kurzor kikapcsolása
ChangeBits(LCD_PORT,0x30,LCD_MASK);
lcd_toggle_E ();
delay_ms(5); //várjunk legalább 4.1ms-ot
lcd_toggle_E ();
__delay_cycles(100); //várjunk legalább 100us-ot
lcd_toggle_E ();
__delay_cycles(40); //várjunk legalább 37us-ot
ChangeBits(LCD_PORT,0x20,LCD_MASK); //0x20 = 4-bites üzemmód
lcd_toggle_E ();
delay_ms(5); //várjunk legalább 4.1ms-ot
//-- Innen kezdve minden bájtot két félbájtként kell kiírni! ------
lcd_write(0x28,0); // display mód beállítás
delay_ms(5); //várjunk legalább 4.1ms-ot
lcd_write(0x08,0); // display letiltás
lcd_write(0x01,0); // képernyo"törlés
lcd_write(0x0C,0); // display be, cursor, és villogás ki
}
/**----------------------------------------------
* Karakterfüzér kiírása az LCD-re
*-----------------------------------------------
* param p_str karakterfüzér mutató (nullával lezárt stringre mutat)
*/
void lcd_puts(char* p_str) {
char c;
while ((c=*p_str)) {
lcd_write(c,1);
p_str++;
}
}
void outdec(long data, unsigned int ndigits) {
static char sign, s[12];
unsigned int i;
i=0; sign='+';
if(data<0) { sign='-'; data = -data;}
do {
s[i]=data%10 + '0';
data=data/10;
i++;
if(i==ndigits) {s[i]='.'; i++;}
} while(data>0);
lcd_write(sign,1);
do{
lcd_write(s[--i],1);
} while(i);
}
long temp;
long IntDegC;
int main(void) {
WDTCTL = WDTPW + WDTHOLD; //watchdog letiltása
ADC10CTL1 = INCH_10 + ADC10DIV_3; // Temp Sensor ADC10CLK/4
ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;
__enable_interrupt(); // Enable interrupts.
TACCR0 = 30; // Delay to allow Ref to settle
TACCTL0 |= CCIE; // Compare-mode interrupt.
TACTL = TASSEL_2 | MC_1; // TACLK = SMCLK, Up mode.
LPM0; // Wait for delay.
TACCTL0 &= ~CCIE; // Disable timer Interrupt
__disable_interrupt();
P1DIR |= BIT0;
P2DIR |= BIT5;
P2OUT_bit.P5 = 1; //Mivel az Lcd kijelzőn van egy pnp így magasra állítom
lcd_init();
lcd_puts(" En szobam ");
lcd_write(0xC0,0); //A második sor elejére lép
lcd_puts("Temp : ");
lcd_puts("+1 ");
lcd_write(0xDF,1);
lcd_puts("C");
while(1){
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
__bis_SR_register(CPUOFF + GIE);
temp = ADC10MEM;
IntDegC = ((temp - 673) * 423) / 1024;
lcd_write(0xC7,0);
outdec(IntDegC,0);
P1OUT ^= BIT0;
delay_ms(1000);
}
}
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
__bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)
}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void ta0_isr(void)
{
TACTL = 0;
LPM0_EXIT; // Exit LPM0 on return
}
Egyelőre még csak ilyen ctrl+c/v de már írom a header fájlt az LCD-mhez minden féle opcióval.
C nyelvű programozáshoz sok ötlet meríthető a honlapomon található PIC18 és PIC24 tananyagokból.
/** Decimális kiíratás adott számú tizedesjegyre.
* \param data a kiírandó szám (előjelesen)
* \param ndigits a kiírandó tizedesek száma
*/
void outdec(long data, unsigned int ndigits) {
static char sign, s[12];
unsigned int i;
i=0; sign='+';
if(data<0) { sign='-'; data = -data;}
do {
s[i]=data%10 + '0';
data=data/10;
i++;
if(i==ndigits) {s[i]='.'; i++;}
} while(data>0);
lcd_write(sign,1);
do{
lcd_write(s[--i],1);
} while(i);
}
Az első paraméter a kiírandó szám ( előjeles 32 bites egész), a második paraméter a levágandó tizedesek száma.
Például, ha a feszültség mV egységekben van megadva, akkor outdec(3300,3) hatására +3.300 íródik ki.
Ha a hőmérséklet tizedfokokban adott, akkor
outdec(273,1) hatására +27.3 íródik ki. Természetesen az ADC-ből kiolvasott értéket előbb skálázni kell, hogy tizedfokokra alakítsuk.
|
|