MSP430 PWM (Pulsweitenmodulation)

msp430_pwm00In diesem kleinen Beispiel-Programm wird eine LCD-Hintergrundbeleuchtung per PWM (Pulsweitenmodulation) gesteuert. Das PWM Signal wird in Abhängigkeit von einem angeschlossenen Potentiometer am MSP430 erzeugt. Zum Einsatz kommt ein DOGM162-Display + das zugehörige Beleuchtungsmodul. Das LCD zeigt die aktuelle LED-Helligkeit in Prozent an (entspricht der Pulsbreite bzw. Duty-Cycle).

Video

PWM-Erzeugung

Es gibt verschiedene Möglichkeiten eine Pulsweitenmodulation zu erzeugen. Da der MSP430 (in diesem Beispiel kommt ein MSP4302452 zum Einsatz) einen Timer besitzt, kann direkt per Hardware eine PWM erzeugt werden. Der Timer besitzt zwei “Capture/Compare Register”, TACCR1 und TACCR0. In diesen beiden Register stehen die Werte, bei denen etwas passieren soll, wenn das TA-Register (TimerA Counter) den Wert im TACCR1 oder TACCR0 erreicht (Interrupt auslösen, Port togglen, Port setzen, Port zurücksetzen). Danach wird TAR wieder auf 0 gesetzt oder zählt wieder von einem bestimmten Wert hoch bzw. runter (je nach Modus).

In diesem Beispiel steht die Periodendauer in TACCR0 und die Pulsbreite (Duty-Cylce) in TACCR1. Der Timer läuft im Up-Mode, zählt also bis zu den zwei Werten in TACCR0 und TACCR1 hoch, wird danach wieder auf 0 gesetzt und zählt wieder hoch usw. Wird der erste Wert in TACCR1 (Pulsbreite) erreicht, wird der Port zurückgesetzt. Danach wird nach einer gewissen Zeit der Wert in TACCR0 (Periodendauer) erreicht und der Port wird wieder gesetzt. Der zeitliche Verlauf:

timer_pwmAbbildung 1 – PWM mit Timer in Up-Mode

Kleine Werte in TACCR1 erzeugen eine kurze Pulsdauer, große Werte eine längere Pulsdauer.

Über das angeschlossene Potentiometer (am 10bit-ADC), werden Integer-Werte zwischen 0-1023 eingelesen. Über eine Geradengleichung wird die Pulsbreite (Zyklen für den Timer) berechnet.

pwm04_1 pwm104_2 pwm04_3

Schaltplan

Das Launchpad wird über einen externen LDO (3,3V) betrieben.

msp430_pwm

C-Programm

main.c

/*******************************
 *          __                   
 *         /\ \                  
 *  __  _  \_\ \     __    ___   
 * /\ \/'\ /'_' \  /'__'\ /'___\ 
 * \/>  <//\ \ \ \/\  __//\ \__/ 
 *  /\_/\_\ \___,_\ \____\ \____\
 *  \//\/_/\/__,_ /\/____/\/____/
 * 
 *  Author: declis (xdec.de)
 ********************************/ 

#include <msp430g2452.h>
#include "lib_lcd.h"
#include "delay.h"

#define cycle		326				// 100Hz, T=10ms
#define delay_ms	5				// delay in ms
#define adc_res		1023			// 10bit ADC
const char bright[]={"Brightness:"};

void main(void)
{
	unsigned long duty_cycle=0;
	unsigned int adc_old=0;

	WDTCTL=WDTPW+WDTHOLD;			// stop WDT
	BCSCTL1=CALBC1_1MHZ;        	// set DCO to 1MHz, set range
  	DCOCTL=CALDCO_1MHZ;				// set DCO step+modulation
	init_USI();						// initialize USI
	init_LCD();						// initialize LCD (DOGM162)

	P1DIR|=BIT2;					// P1.2 -> output
	P1SEL|=BIT2;					// P1.2 -> compare: Out1 output (TA0.1)
	TACCR0=cycle;					// CCR0 -> cycle time (10ms)
	TACCR1=0;						// CCR1 -> duty cycle
	TACCTL1=OUTMOD_7;				// reset/set
	TACTL=TASSEL_1+MC_1;			// CLK-source=32kHz, up-mode

	BCSCTL3|=XCAP_3;				// CL=~12.5pF
	do
	{
		IFG1&=~OFIFG;
		wait_ms(1);
	}
	while(IFG1&OFIFG);

	//Channel 0 (Poti); ADC10 CLK divider = /4; CLK=ADC10OSC
  	ADC10CTL1=INCH_0+ADC10DIV_3+ADC10SSEL_0;
  	//Vref+=Vcc (ext. LDO 3.3V) and Vss=Vr-; S&H time 16x; ADC10 on
  	ADC10CTL0=SREF_0+ADC10SHT_3+ADC10ON;
  	// P1.0 is analog input
  	ADC10AE0|=BIT0;

	write_string(0,0,bright);
	write_char(14,0,'%');
	while(1)
	{
		wait_ms(delay_ms);
		ADC10CTL0|=ENC+ADC10SC;					// start & enable conversion
		while(ADC10CTL0&ADC10BUSY);				// ADC busy?

		// if we don't have a new ADC value, do nothing and wait
		if(adc_old!=ADC10MEM)
		{
			// y=mx+b
			duty_cycle=((cycle*(unsigned long)ADC10MEM)/adc_res);
			TACCR1=duty_cycle;
			adc_old=ADC10MEM;
		}
		// duty cycle in percent -> duty-cycle=(cycle/100)*percent
		char_to_num_out(12,0,(duty_cycle*100)/cycle);
	}
}

 

DIe restlichen Files gibt es hier: DOWNLOAD SOURCE

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

This site uses Akismet to reduce spam. Learn how your comment data is processed.