AD-Wandler, PWM und Pullups


Elektronik-Labor  Projekte   Holtek



Der HT46F47E besitzt einen 8-Bit-PWM-Ausgang, genauer einen 6+2-Bit oder wahlweise 7+1-Bit-Ausgang, was dazu führt, dass sie PWM-Frequenz relativ hoch ist. Die Anwendung ist sehr einfach, man muss nur den zugehörigen Port D0 auf Ausgang schalten und hochsetzen. Das Datenblatt enthält ein Assembler-Beispiel, das hier in C umgesetzt wurde. Dazu wurde einfach das letzte C-Programm für die Verkehrsampel erweitert. 

	_pdc0 = 0;    //PC0 Ausgang
_pd0 = 1; //PWM einschalten
_pwm = 100; //PWM-Ausgabe 0...255
Damit wirklich ein PWM-Signal am Pin 10 herauskommt, muss vorab aber noch das entsprechende Option-Bit gesetzt werden:



Der AD-Wandler bat vier mögliche Eingangskanäle am Port B. Hier ist keine Option-Einstellung nötig, d.h. man könnte den Port B im gleichen Programm wahlweise als Port und als AD-Wandler verwenden.

	_eadi = 0;     //Kein Interupt
_acsr = 1; //AD-Clock = 1/8

while (1){
_adcr = 8; //nur B0 als ADC0, AdC0 gewaehlt
_start=0;
_start=1; //AD-Start
_start=0;
while (_eocb == 1);
u = _adrh; //Aufloesung 8 Bit
_pwm = u; //PWM-Ausgabe
_delay(65000);
}


Der AD-Wandler hat eine Auflösung von 9 Bit. Wenn man aber nur das Highbyte ADRH ausliest, beträgt die Auflösung 8 Bit, passend zur PWM-Ausgabe. Das Beispiel misst laufend die Spannung an Port B0 und gibt das Ergebnis am PWM-Ausgang aus. Zum Test habe ich einen LDR im Spannunsgteiler mit 27 kOhm verwendet. Am PWM-Ausgang liegt eine rote LED mit 1 kOhm. Die LED wird heller, je geringer die Helligkeit am LDR ist.




Im nächsten Schritt sollte versucht werden, die noch freien Eingänge am Port B (B1...B3) als Eingänge mit Pullup zu nutzen. Die Pullups müssen wieder in den Options eingeschaltet werden. Das Ergebnis kann mit dem Voltmeter bestätigt werden. Der Pullup liegt laut Datenblatt bei ca. 30 kOhm. Es wurde ein Kurzschlussstrom von 170 µA gemessen, passt.



Das Programm wird nun um eine Auswahl erweitert: Je nachdem, ob und welcher Porteingang an B1...2 auf Masse gezogen wird, hat man einen Dämmerungsschalter, eine Zählschleife oder eine Ampel. Nur so zum Üben ...

#include "HT46F47E.h"

const unsigned char table[16]={
0x14, 0x4, 0x14, 0x4, 0x14, 0x4, 0x14, 0x24,
0x41, 0x40, 0x41, 0x40,0x41, 0x40, 0x41, 0x42 };

#pragma vector isr_4 @ 0x4
#pragma vector isr_8 @ 0x8
#pragma vector isr_c @ 0xc

//ISR for safequard
void isr_4(){} // external ISR
void isr_8(){} // timer/event 0
void isr_c(){} // timer/event 1

//initialize registers for safeguard
void safeguard_init(){
_intc = 0;
_tmrc = 0;
_tmr = 0;
_pac = 0xff; //input mode
_pbc = 0xff;

}

//a long time delay
void mydelay(unsigned int times){
while(times--) _delay(65000);
}

void main(){
unsigned char i, j, idx, u, pb;

safeguard_init();

_pac = 0; //set port A to output port
_pa = 0; //zero port A (all light on)

_pdc0 = 0; //PC0 Ausgang
_pd0 = 1; //PWM einschalten
_pwm = 100; //PWM-Ausgabe 0...255

_eadi = 0; //Kein Interupt
_acsr = 1; //AD-Clock = 1/8

while (1){

pb = (_pb >> 1) & 7;

if (pb == 7) {
_adcr = 8; //nur B0 als ADC0, AdC0 gewaehlt
_start=0;
_start=1; //AD-Start
_start=0;
while (_eocb == 1);
u = _adrh; //Aufloesung 8 Bit
_pwm = u; //PWM-Ausgabe
_delay(65000);
}

if (pb == 6) {
for(i=0; i!=255; i++){
_pa = i;
mydelay(50);
}
}

if (pb == 5) {
idx = 0;
for(i=0; i!=2; i++) {
_pa = table[idx];
idx++;
mydelay(8);
for(j=0; j!=6; j++) {
_pa = table[idx];
idx++;
mydelay(1);
}
_pa = table[idx];
idx++;
mydelay(4);
}
}
}
}


Download: Projektverzeichnis C_test: C_test1b.zip


Elektronik-Labor  Projekte   Holtek