//pwm.c
#include <iocc2540.h>
#include "pwm.h"
//pwm pins:
//P0_3:R (TX)--ch1
//P0_4:G (CTS)--ch2
//P0_5:B (RTS)--ch3
static uint16 gRed =1;
static uint16 gGreen =1;
static uint16 gBlue =1;
void PWM_Init()
{
//设置pwm端口为输出
P0DIR|= BV(3)|BV(4)|BV(5);
//设置pwm端口为外设端口,非gpio
P0SEL|= BV(3)|BV(4)|BV(5);
//由于uart等会占用我们当前使用的pwm端口,因此需要将uart等重映射到别的端口去。
PERCFG |= 0x03; // Move USART1&2 to alternate2 location so that T1 is visible
// Initialize Timer 1
T1CTL = 0x0C; // Div = 128, CLR, MODE = Suspended
T1CCTL1 = 0x0C; // IM = 0; CMP = Clear output on compare; Mode = Compare
T1CCTL2 = 0x0C; // IM = 0; CMP = Clear output on compare; Mode = Compare
T1CCTL3 = 0x0C; // IM = 0, CMP = Clear output on compare; Mode = Compare
T1CNTL = 0; // Reset timer to 0;
//必须设置,否则定时器不工作
T1CCTL0 = 0x4C; // IM = 1, CMP = Clear output on compare; Mode = Compare
//设置周期的tick为375, 也就是1.5ms
#if 1
T1CC0H = 0x01; // Ticks = 375 (1.5ms initial duty cycle)
T1CC0L = 0x77; //
T1CC1H = 0x01; // Ticks = 375 (1.5ms initial duty cycle)
T1CC1L = 0x77;
T1CC2H = 0x01; // Ticks = 375 (1.5ms initial duty cycle)
T1CC2L = 0x77;
T1CC3H = 0x01; // Ticks = 375 (1.5ms initial duty cycle)
T1CC3L = 0x77;
#else//以下设置会是1khz
#define VALUE_H 0x00
#define VALUE_L 0x10
T1CC0H = VALUE_H;
T1CC0L = VALUE_L;
T1CC1H = VALUE_H;
T1CC1L = VALUE_L;
T1CC2H = VALUE_H;
T1CC2L = VALUE_L;
T1CC3H = VALUE_H;
T1CC3L = VALUE_L;
#endif
EA=1;
IEN1 |= 0x02; // Enable T1 cpu interrupt
}
//red, green, blue 的值必须是 1~375, 其他值无效
void PWM_Pulse(uint16 red, uint16 green, uint16 blue)
{
uint16 r,g,b;
// stop,注意,不能加这句,加了周期偏差十几倍,具体原因未查明
//T1CTL &= BV(0)|BV(1);
r=red;
g=green;
b=blue;
// Set up the timer registers
T1CC1L = (uint8)r;
T1CC1H = (uint8)(r >> 8);
//避免比较值为0时,输出一直为高
if(r!=0)
{
T1CCTL1 = 0x0C;
} else
{
T1CCTL1 = 0x00;
}
T1CC2L = (uint8)g;
T1CC2H = (uint8)(g >> 8);
if(g!=0)
{
T1CCTL2 = 0x0C;
} else
{
T1CCTL2 = 0x00;
}
T1CC3L = (uint8)b;
T1CC3H = (uint8)(b >> 8);
if(b!=0)
{
T1CCTL3 = 0x0C;
} else
{
T1CCTL3 = 0x00;
}
// Reset timer
T1CNTL = 0;
// Start timer in modulo mode.
T1CTL |= 0x02;
}
//red, green, blue 的值必须是 1~375, 其他值无效
void PWM_RGB(uint16 red, uint16 green, uint16 blue)
{
gRed=red;
gGreen=green;
gBlue=blue;
}
//#pragma register_bank=2
#pragma vector = T1_VECTOR
__interrupt void pwmISR (void)
{
uint8 flags = T1STAT;
// T1 ch 0
if (flags & 0x01)
{
// Stop Timer 1
//T1CTL |= 0x02;
//red, green, blue 的值必须是 1~375, 其他值无效
PWM_Pulse(gRed,gGreen,gBlue);
}
T1STAT = ~ flags;
}
//pwm.h
#ifndef __PWM_H__
#define __PWM_H__
#include <iocc2540.h>
#define uint8 unsigned char
#define uint16 unsigned short
#define BV(n) (1 << (n))
void PWM_Init();
void PWM_Pulse(uint16 red, uint16 green, uint16 blue);
void PWM_RGB(uint16 red, uint16 green, uint16 blue);
#endif
//main.c
#include "pwm.h"
//(375/2)--------305.8-3.2-48.8
//(375)----------305.8-3.2-97.8
//(375*100/10)---
#define R_CYCLE (375/2)
#define G_CYCLE (375/2)
#define B_CYCLE (375/2)
void init_clock(void)
{
CLKCONCMD &= ~0x40; //设置系统时钟源为 32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振稳定
CLKCONCMD &= ~0x47; //设置系统主时钟频率为 32MHZ
}
void main(void)
{
IEN0 = IEN1 = IEN2 = 0x00;
init_clock();
PWM_Init();
PWM_RGB(R_CYCLE,G_CYCLE,B_CYCLE);
PWM_Pulse(R_CYCLE,G_CYCLE,B_CYCLE);
while(1)
{
}
}
教程的测试结果是周期是1.5MS,但是本人测试周期是3MS。不知道本人哪里弄错。
测试结果:
image.png
网友评论