G.I.P: automatisch schaduwstation zonder wissels

Gestart door conducteur, 09 mei 2012, 21:33:26 PM

MickeyMouse

Citaat van: conducteur op 24 januari 2014, 14:36:46 PM
...weer iets bijgeleerd, één pin van een poort setten/clearen zonder die ambetante logische bewerkingen op ganse poort van de µC
...
Ik weet niet hoe dit bij de huidige pics is, maar niet alle processoren zullen die bit-commando's naar poorten ondersteunen hoor. Bij sommigen zijn het zelfs maar bepaalde poorten die dit supporteren.
Als je programmeerwerk op controllerniveau wilt doen zul je met and-en, or-ren, exor-en, enzo toch moeten kunnen spelen hoor, desnoods via voorgedefineerde #define's. Ook voor periferie-chips is dit vele keren nodig!!
Bitneukerij noemen wij dit....

Libraries: ik vermoed dat hiermee het schrijven van functies bedoeld wordt welke je dan verzamelt in een aparte .c-file, bvb alles voor je lcd plaats je in lcd.c --> routines om een bepaalde tekst op een bepaalde positie te zetten bvb...

Succes ermee en blijven volhouden tot het ding doet wat je wilt dat het doet en vooral waarom!!


Geert




conducteur

#421
Nu nog de LCD en de SPI en dan is dit deel al voor 95% gereed
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum

Sattrickske

4x te traag, dat lijkt erop dat er geen rekening gehouden werd met de interne klok van de PIC16.  Als je quartz kristal effectief 20MHz is, dan draait je interne klok op 5MHz (zonder PLL), omdat de PIC16 4 klokcycli nodig heeft om één instructie uit te voeren.  Dus je moest _XTAL_FREQ op 5000000 zetten...

Je hebt eigenlijk al een bibliotheek gebruikt, de htc.h die onrechtstreeks de Hi-Tech delay routines bevat, deze zijn niet super nauwkeurig maar kunnen ermee door.
Ik wou je een delay routine in een eigen bibliotheek laten zetten en via een include in je main programma opnemen.  Als je kijkt naar mijn LCD code, zie je bovenaan 3 includes:
#include <htc.h>
#include "lcd.h"
#include "delay.h"

De eerste is een 'globale' include (gaat het volledige path afzoeken naar de header).  De laatste 2 zijn 'locale' includes, in dit geval staan ze in dezelfde directory als de code (daar waar lcd.c staat).
In de header stop je voornamelijk constanten en signaturen van routines.  Elke header heeft een .c file nodig met de implementatie van de routines die je in de .h geplaatst hebt.  Je moet er enkel voor zorgen dat de compiler en linker aan dit bestand aankunnen.  Dat kan op verschillende manieren, de eenvoudigste is om alle .c bestanden in één en dezelfde directory onder te brengen.  Een andere manier is om de benodigde .c bestanden te includen in je hoofdprogramma, dan kan je relatieve paths gebruiken en blijft je project netjes.

De bedoeling was nu om je ledje te laten knipperen door zelf een delay functie te schrijven en niet deze van htc te herbruiken.  Een goede, precieze delay is niet zo moeilijk om te schrijven.  Je moet nagaan hoeveel tijd er in elke instructie 'verloren' gaat (klokcycli tellen).  Hieronder heb je mijn delay routines die geldig zijn voor verschillende klokfrequenties (opgelet klok is niet gelijk aan kristal):

delay.h

#ifndef __DELAY_H__
#define __DELAY_H__

#ifndef CLK_FREQ
#define CLK_FREQ 4000000
#endif

extern unsigned char delayus_variable;

#if CLK_FREQ == 4000000
#define DelayDivisor 4
#define WaitFor1Us asm("nop")
#define JumpBack asm("goto $-4")
#elif CLK_FREQ == 8000000
#define DelayDivisor 2
#define WaitFor1Us __asm__("nop")
#define JumpBack __asm__("goto $-4")
#elif CLK_FREQ == 12000000
#define DelayDivisor 1.5
#define WaitFor1Us __asm__("nop")
#define JumpBack __asm__("goto $-4")
#elif CLK_FREQ == 16000000
#define DelayDivisor 1
#define WaitFor1Us __asm__("nop")
#define JumpBack __asm__("goto $-4")
#elif CLK_FREQ == 20000000
#define DelayDivisor 1
#define WaitFor1Us __asm__("nop\nnop")
#define JumpBack __asm__("goto $-6")
#elif CLK_FREQ == 32000000
#define DelayDivisor 1
#define WaitFor1Us __asm__("nop\nnop\nnop\nnop\nnop")
#define JumpBack __asm__("goto $-12")
#elif CLK_FREQ == 40000000
#define DelayDivisor 1
#define WaitFor1Us __asm__("nop\nnop\nnop\nnop\nnop\nnop\nnop")
#define JumpBack __asm__("goto $-16")
#elif CLK_FREQ == 48000000
#define DelayDivisor 1
#define WaitFor1Us asm("nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n")
#define JumpBack asm("goto $-20")
#else
#error delay.h - please define CLK_FREQ corectly or add more supported clock frequencies
#endif

#define DelayShortUs(x) {\
delayus_variable=(unsigned char)(x/DelayDivisor); \
asm("movlb (_delayus_variable)");\
WaitFor1Us; }\
asm("decfsz (_delayus_variable),f");\
JumpBack;

void DelayUs(unsigned int us);
void DelayMs(unsigned int ms);

#endif/*__DELAY_H__*/


delay.c

#include "delay.h"
void DelayMs(unsigned int ms) {
    unsigned char i = 4;
    while (ms-- > 0) {
        i = 4;
        while (i-- > 0) {
            DelayShortUs(250);
        }
    }
}

void DelayUs(unsigned int us) {
    unsigned char quartz = us >> 8;
    while (quartz-- > 0) {
        DelayShortUs(0xff);
    }
    DelayShortUs(us & 0xff);
}


Vooral de delay.h zal je wat kopzorgen bezorgen, maar deze is zo optimaal mogelijk gemaakt met compiler directieven.  Dit is nodig omdat floating point operaties zeer kostelijk zijn op de PIC12/PIC16/PIC18, daarom heb ik m'n meest voorkomende klokfrequenties hierin gedefinieerd.  De jouwe van 5MHz zit er niet tussen, dat laat ik aan jou over om correct uit te rekenen.  Hint, 't is kleiner dan 16MHz, dus 1 NOP en een divisor >1 gebruiken.


Als je timing in de delays goed zit, moet m'n LCD routine ook werken.  Vergeet niet om m'n 8bit interface om te zetten naar 4 bit.  Tijdens de initialisatie moet je LCDCommand(0x38) vervangen door LCDCommand(0x28).  En je moet de LCDCommand en LCDPut routines wat herschrijven: 4 bits per keer doorsturen door telkens de LCD_E aan en uit te toggelen na elke 4 bits.

PeterC

Citaat van: Sattrickske op 25 januari 2014, 00:20:00 AM
...Dus je moest _XTAL_FREQ op 5000000 zetten...

Citaat van: Sattrickske op 25 januari 2014, 00:20:00 AM
...opgelet klok is niet gelijk aan kristal...

Ik denk dat we hier toch op een verschillende golflengte zitten:  volgens mij moet _XTAL_FREQ ingesteld staan op de werkelijke klokfrequentie dus op 20000000.  4 klokcycli per instructie is inderdaad zo en is de verwerkingstijd van de instructies dus 1/4° van de klokfrequentie maar de constante moet wel degelijk op de werkelijke klokfrequentie staan...
De klokfrequentie wordt wel degelijk op volle snelheid benut voor de periferie (ADC, timers, ...).

Citaat van: Sattrickske op 25 januari 2014, 00:20:00 AM
...Als je quartz kristal effectief 20MHz is, dan draait je interne klok op 5MHz (zonder PLL)...

Zijn er PIC16 met een PLL?  Ik heb enkel weet van de 18F serie met USB interface (18F2455, 2550, 4455 en 4550).  Een PIC16 met PLL zou me wel interesseren.  Voor sommige toepassingen kom ik net wat klok te kort...



Citaat van: conducteur op 22 januari 2014, 14:11:59 PM
ps: (n)iemand goesting om eens op een zaterdag of zondagnamiddag in februari me even op weg te helpen met dit project?

Ja!  Er rijden treinen van Blankenberge naar Deinze (via Gent) en van het station is het 3 minuten en 22 seconden te voet tot bij mij thuis.  ...Maar C heb ik al een ganse tijd achter mij gelaten en is ondertussen al heel roest geworden...
Hitech C heb ik hier staan en ik wil wel een poging wagen. 
Als je het boek van Bert Van Dam ondertussen al hebt doorgenomen, wordt het JAL.
Graag afspreken via PM.

Groetjes, Peter


Sattrickske

Citaat van: PeterC op 25 januari 2014, 01:15:30 AM
Citaat van: Sattrickske op 25 januari 2014, 00:20:00 AM
...Dus je moest _XTAL_FREQ op 5000000 zetten...

Citaat van: Sattrickske op 25 januari 2014, 00:20:00 AM
...opgelet klok is niet gelijk aan kristal...

Ik denk dat we hier toch op een verschillende golflengte zitten:  volgens mij moet _XTAL_FREQ ingesteld staan op de werkelijke klokfrequentie dus op 20000000.  4 klokcycli per instructie is inderdaad zo en is de verwerkingstijd van de instructies dus 1/4° van de klokfrequentie maar de constante moet wel degelijk op de werkelijke klokfrequentie staan...
De klokfrequentie wordt wel degelijk op volle snelheid benut voor de periferie (ADC, timers, ...).
Je zou kunnen gelijk hebben. Ik weet het niet meer zeker, ik gebruik al een hele tijd XC8 of SDCC en zeker niet meer de 'ingebouwde' delay functies.  Dus hoe het juist zat met die goeie ouwe Hi-Tech, weet ik niet meer.   En om alle verwarring uit te schakelen (werd heel lastig als je verschillende types µC door mekaar gebruikt en niet alleen PIC), gebruik ik mijn delay.h enkel de 'CPU klok' of 'instructie cyclus' als je wil; dus de effectieve tijd die er nodig is om één instructie uit te voeren.  Maar soit da's een gans ander verhaal.
Maar als Rian zegt dat z'n ledje 4x te traag knippert, is dit wel de quick en dirty oplossing ;).  Maar hij zal wel op langere termijn moeten nakijken waarom ie 4x te traag is.  De PIC16F877 heeft geen speciale setup voor de klok, dus verkeerd kristal?

Citaat van: PeterC op 25 januari 2014, 01:15:30 AM
Citaat van: Sattrickske op 25 januari 2014, 00:20:00 AM
...Als je quartz kristal effectief 20MHz is, dan draait je interne klok op 5MHz (zonder PLL)...

Zijn er PIC16 met een PLL?  Ik heb enkel weet van de 18F serie met USB interface (18F2455, 2550, 4455 en 4550).  Een PIC16 met PLL zou me wel interesseren.  Voor sommige toepassingen kom ik net wat klok te kort...
Neen, niet dat ik weet, enkel een paar PIC18F, de PIC24 en PIC32.  Microcontrollers werken heel goed met kwartsen tot 40-48MHz (afhankelijk van het type), daarboven worden ze onstabiel en schakelen ze over naar lagere frequenties voor het kristal en combineren ze dat met een PLL.  M'n STM32F407 draait met een kristal van 8 MHz een klok van 168 MHz (!).

Sattrickske

Ik heb deze middag wat tijd...
Ik zal effe jouw configuratie voor de LCD1602 aan m'n test bord met PIC16F877 hangen.  Als je me via PM je e-mail adres doorgeeft, zal ik je ten laatste tegen maandagavond een MPLab X project doorsturen met daarin:
- main.c (hoofd programma)
- board.h (configuratie de gebruikte schakeling)
- delay.h (delay headers)
- delay.c (delay implementatie)
- lcd.h (LCD headers)
- lcd.c (LCD implementatie)

De gebruikte compiler is XC8 (free version).  Op deze manier heb je dan een volledig correcte configuratie van PIC16F C project en kan je dan verder met het aanmaken van andere bibliotheken in dezelfde zin als m'n delay en lcd.

conducteur

#426
In de voorbeeldprogramma's die we in de lessen gebruikt hebben staat wel degelijk


#define _XTAL_FREQ  19660800     // oscillator frequency for _delay() dus 19,6608 MHz...  Dus moet ik met een 20MHz kristal toch 20 000 000 invullen?


KIEKENMODUS ON
Ik denk dat het kristal op de verkeerde pins aangesloten is, hoe ik dat gedaan heb, geen idee...
Eens veranderen als ik tijd heb, maar eerst Java leren voor examens...
KIEKENMODUS OFF


JAL: ik heb het boek in de boekhandel besteld, omdat ik nog een cadeaubon gekregen heb bij m'n attest hogere graad deeltijds kunstonderwijs afdeling muziek, omdat ik vorig jaar het laatste jaar cello gevolgd heb aan de muziekschool. Maar ik heb de indruk dat de drukpers nog moet ingesteld worden, nog steeds geen boek...
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum

PeterC

Citaat van: conducteur op 25 januari 2014, 11:47:24 AM
KIEKENMODUS ON
...
KIEKENMODUS OFF

:) :) :) Uit je fouten moet je leren  ;)

Mail mij eens je schema; ik zal in Hi tech eens kijken of ik het roest nog van mijn C krijg...
Ik heb geen 887 op voorraad, maar wel nog enkele 877's liggen.  Zal daar eens mee proberen voor je LCD.



Groetjes, Peter


conducteur

Dan schakelt de pic automatisch over naar een interne oscillator, als er toch geen kristal is aangesloten?
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum

Geert

De PIC schakelt niet automatisch over naar de interne oscillator. Welke oscillator de PIC gebruikt (kristal, RC, intern...) wordt hardwarematig ingesteld (__CONFIG in assembler)

Geert
Schaal H0 - digitaal zelfbouw - Favoriete Lok: V200 DB

Sattrickske

Neen je PIC kiest niet zomaar een klok, daarvoor moet je de fuses aanpassen.  Je PIC klok draaide op interferentie, kan soms werken, maar is zo onstabiel als de pest.

Maar ik heb ondertussen je projectje klaar in een zip bestandje
Het enige wat je dient aan te passen, is de board_16F877A.h file en er jouw schema op koppelen.  Als alles correct werkt, zou je dit moet krijgen:


EDIT: vergeten bij te zeggen, dat de timing in 4-bit heel belangrijk is.  Kijk naar de LCDInit, vooral de eerste 4 instructies zijn cruciaal.  En controleer ook of je contrast wel goed is, anders krijg je  steeds een blank scherm te zien.

conducteur

#431
Het klok probleem is ondertussen opgelost... Het ledje pinkt aan de juiste snelheid met
#define _XTAL_FREQ  20000000     // oscillator frequency for _delay() .

straks eens naar je zipje kijken, bedankt ervoor, maar eerst nog wat JAVA
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum

MickeyMouse

Citaat van: conducteur op 25 januari 2014, 17:33:30 PM
Het klok probleem is ondertussen opgelost... Het ledje pinkt aan de juiste snelheid met
#define _XTAL_FREQ  20000000     // oscillator frequency for _delay() .

straks eens naar je zipje kijken, bedankt ervoor, maar eerst nog wat JAVA
Goed dat je het ontdekt hebt!!
En met de input van Patrick zal de aansturing van het display ook wel in orde komen...

Geert

MickeyMouse

Patrick,

Mooi dat je Rian zo op weg zet, in C is stap voor stap gaan sowieso de beste leerschool.

@Rian: Nu proberen om iedere regel van Patrick zijn voorbeelcode te begrijpen...
Een werken display is ook, en vooral, bij het debuggen heel interessant!!

Geert

conducteur


/*
* File:   board_16F877A.h
* Author: Patrick
*
* Created on 25 januari 2014, 11:38
*/


#ifndef BOARD_16F877A_H
#define   BOARD_16F877A_H


#pragma config FOSC = HS, LVP = OFF, CP = OFF, WDTE = OFF, BOREN = OFF


#define CLK_FREQ 20000000


#define CONFIGURE_CHIP  TRISC &= ~0x80;ADCON1=0X07


#define LCD_DATA        PORTD
#define LCD_DATA_TRIS   TRISD
#define LCD_CTRL_TRIS   TRISD &= ~0x0E
#define LCD_RS          PORTDbits.RD4
#define LCD_E           PORTDbits.RD5


#define LCD_RW          PORTAbits.RD2


#endif   /* BOARD_16F877A_H */


Klopt dit?


DB4-DB7 van lcd op RD0-RD3,RS op RD4, E op RD5




en dan in main.c het project compileren? Dan krijg ik die error die in delay.h staat, hoewel voor zo ver ik het begrijp de #define CLK_FREQ 20000000 juist gedefineerd is en ook in delay.h staat... 


compiler:
#error delay.h - please define CLK_FREQ corectly or add more supported clock frequencies
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum