Hi, Robots(三):The RTCLP——基于软件PWM

The RTCLP——The Randomly Three Color LED Project,今天终于完成了(其实也就从昨天开始搞……)。顾名思义,由RGB三色LED灯合成颜色,组成一盏变化的“灯”,灯的颜色是随机变化的,并且带渐变。实际上The RTCLP是上次讲的基于软件的PWM的应用,因为确确实实里面用到了上次的PWM.c。

说下思路吧,三路PWM控制RGB三种颜色,为了增强亮度,就将每一路又复制两份(PORTC->PORTA、PORTB)。开始时准备打一个颜色表,然后定时切换,后来发现效果不理想。想想,既然这次用了16.9344MHz的晶振,那干脆引用用随机函数吧,反正速度够快。事实上也确实是,产生一次随机数只要73μs。写了一个SetPWM(char,char,char),用来修改亮度,实际上是渐变的,每一次+1或-1,直到到达目标。本想写一个for简介一点,但是想到还要写个全局数组,而数组相当占时间(其实是懒啦,毕竟晶振够快),所以就用老土的Copy&Paste写了三次。SetPWM里面的那个delay就是用来控制颜色变化的快慢的。其他方面基本上没有什么好说的了。

挺郁闷的是,要过年了没有提前买元件,所以LED灯都凑不齐……╮(╯▽╰)╭要三个高亮散光的LED,结果只有一个高亮散光的R、一个普通亮度的G、一个高亮聚光的B……过几天再弄弄吧……

代码如下: main.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
 * The Randomly Three Color LED Project (The RTCLP)
 * Author     :  abcdabcd987
 * Date       :  2010-02-02
 * Happy Spring Festival!
 *
 * Something is required:
Software PWM  -  (abcdabcd987) to provide PWM control
PICC          -  (  HI-TECH  ) to complie the source
 *
 * The Project Has Built Successfully under PICC9.80(Lite Mode)
 * The MCU Infomation:
Device        :  PIC16F73
Frequency     :  16.9344MHz
Output(R)     :  RA0, RB0, RC0
Output(G)     :  RA1, RB1, RC1
Output(B)     :  RA2, RB2, RC2
Vdd           :  About 5V
 */
#include "header.h"
#include <stdlib.h> // For rand() and srand();
__CONFIG(0x273A);
int main();
void delay(int);
void SetPWM(char, char, char);

int main()
{
  ADCON1 = 0x7;
  PWM_Init(0b00001100, 249);
  PWM_SetPWM(0, 0);
  PWM_SetPWM(1, 0);
  PWM_SetPWM(2, 0);
  srand(1);

  while(1)
      SetPWM(rand(), rand(), rand());
}
void SetPWM(char p1, char p2, char p3)
{
  //Range Check:
  if (p1 > _maxpwm) p1 -= _maxpwm;
  if (p2 > _maxpwm) p2 -= _maxpwm;
  if (p3 > _maxpwm) p3 -= _maxpwm;
  //Gradual Change:
  char done = 0;
  while (done < 7)
  {
      char value;
      //Color 1:
      if (!(done&1))
      {
          value = _pwm[0];
          if (value == p1)
              done|=1;
          else if (value > p1)
              --_pwm[0];
          else
              ++_pwm[0];

      }
      //Color 2:
      if (!(done&2))
      {
          value = _pwm[1];
          if (value == p2)
              done|=2;
          else if (value > p2)
              --_pwm[1];
          else
              ++_pwm[1];

      }
      //Color 3:
      if (!(done&4))
      {
          value = _pwm[2];
          if (value == p3)
              done|=4;
          else if (value > p3)
              --_pwm[2];
          else
              ++_pwm[2];

      }
      //!!!!MOST IMPORTANT THING: DELAY!!!!
      delay(0x4fff);
  }
}
void delay(int x)
{
  while (--x);
}
void interrupt breakdown()
{
  PWM_interrupt();
}

PWM.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
 * The Randomly Three Color LED Project (The RTCLP)
***Used and Modified by abcdabcd987 2011-02-02
*/
/*
 * Software PWM by abcdabcd987 2011-1-2
 * There is something to write into your header:
extern unsigned int _T;
extern const char _maxpwm;
extern char _pwm[_tol];
extern char _sta[_tol];
extern void PWM_Init(const char, const char);
extern void PWM_interrupt();
extern void PWM_SetPWM(const char, const char);
extern void PWM_Stop();
 * Use PWM_init(t2con, pr2) to start the software PWM.
 * Use PWM_SetPWM(index, value) to set the value of each PWM channel.
 * Add a usage of PWM_interrupt() to your interrupt.
 * You can modify _tol, _prot, _tris(header.h), _maxpwm. Others DO NOT modify.
 */
#include "header.h"
const char _maxpwm = 130;
const char _out[8]={0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};
const char _trisseting[8]={0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x0};
unsigned int  _T;
char _pwm[_tol];
char _sta[_tol];
void PWM_Init(const char, const char);
void PWM_SetPWM(const char, const char);
void PWM_interrupt();
void PWM_Stop();

void PWM_Init(const char t2con, const char pr2)
{
  for (char _i = 0; _i < _tol; ++_i) _sta[_i] = 0;
  _tris &= _trisseting[_tol-1];
  _port = 0;
  TRISA &= _tris;
  TRISB &= _tris;
  PORTA = 0;
  PORTB = 0;
  T2CON = t2con;
  PR2 = pr2;
  TMR2IE = 1;
  PEIE = 1;
  GIE = 1;
  _T = 0;
}
void /*interrupt */PWM_interrupt()
{
  if (TMR2IF)
  {
      TMR2IF = 0;
      char _pt = _port;
      for (char i = 0; i < _tol; ++i)
      {
          _sta[i] = _sta[i] + 1;
          if (_sta[i] >= _maxpwm)
          {
              _pt = _pt | _out[i];
              _sta[i] = 0;
          }
          if (_sta[i]==_pwm[i] && _pwm[i]!=_maxpwm)
          {
              _pt = _pt & (~_out[i]);
          }
      }
      _port = _pt;
      PORTB = _pt;
      PORTA = _pt;
  }
}
void PWM_SetPWM(const char index, const char value)
{
  _pwm[index] = value;
}
void PWM_Stop()
{
  T2CON = 0;
  TMR2IE = 0;
}

header.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 /*
  * The Randomly Three Color LED Project (The RTCLP)
  */
#ifndef HEADER_H
#define HEADER_H
#include <pic.h>
#define _tol 3
#define _port PORTC
#define _tris TRISC
/*PWM start*/
extern const char _maxpwm;
extern char _pwm[_tol];
extern char _sta[_tol];
extern void PWM_Init(const char, const char);
extern void PWM_interrupt();
extern void PWM_SetPWM(const char, const char);
extern void PWM_Stop();
/*PWM   end*/
#endif

Comments