
AD-Wandler, PWM und Pullups
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