国庆假期倒腾了五天,准备搞个手机蓝牙无线控制RGB LED的控制器;本来已经用STM32F103C8T6写好程序了,但这个芯片的成本比较高,如果多搞几个的话,还真心的费钱,且这个芯片用在这个功能上,也太大材小用了。于是准备用价格低廉的STC芯片替代,在购买电子元器件的时候,特意找了一款价格便宜的芯片STC15W201S,价格在3元左右一片吧。本以为很容易的在网上就会找到相关的例程的,没有想到,搜了一下,竟然一个相关的例程也没有找到,泪奔啊。。。
刚好最近在学习电子技术,都买了回来,不管怎样,试一下自己开搞吧,努力百度查询基本资料中。。
先介绍一下STC15W201S的芯片的基本信息吧,芯片的工作电压为2.5V至5.5V,保守点,用3.3V吧;芯片内带高精度RC震荡器且不能外接晶震,在一般的应用场合,连外围的晶震电路都省了,这点值得点赞啊。程序存储为1K,RAM为256字节,还带有4K的EEPROM,这个片内EEPROM还没有测试,下回想用的时候,再测试吧,这个感觉也不错,连外存都不用挂,还是一个字,省!片内有二个定时器,定时器0和定时器2,只有一个串口,但是能分时复用,相当于二个串口,但这点我还没有测试。
程序实现的功能如下,蓝牙模块通过串口与STC15W201S的串口相连接,接收与发送数据。输出五路PWM信号,对红绿蓝黄白五种色的LED灯进行调色及亮度控制。另有一条PWM信号控制输出,用于原灯电路与改装LED灯的控制转换。总不能将原灯的东西全部丢掉吧,加上去就好,通电后默认用原灯,通过控制器转换。
程序烧录参数如下图,需要注意,烧录时,需要将12与13脚的电平拉低才能写入。实物图有点乱,有兴趣看电路图吧,
KEIL代码:
USART.H内容
#ifndef __USART_H__
#define __USART_H__
typedef unsigned char u8;
typedef unsigned int WORD;
#define UNLOCK 0x00; //用于标识数据包的接收状态
#define LOCK 0xff;
#define BAUD 9600 //串口波特率 115200
#define NONE_PARITY 0 //无校验
#define ODD_PARITY 1 //奇校验
#define EVEN_PARITY 2 //偶校验
#define MARK_PARITY 3 //标记校验
#define SPACE_PARITY 4 //空白校验
#define PARITYBIT NONE_PARITY //定义校验位
#define DATA_LEN 7 //定义协议数据位长度
sfr P_SW1 = 0xA2; //外设功能切换寄存器1
#define S1_S0 0x40 //P_SW1.6
#define S1_S1 0x80 //P_SW1.7
extern bit busy;
extern unsigned int buf_num;
extern u8 rev_buf[6];
void Usart_Int(void);
void SendData(u8 dat);
void SendString(char *s);
void Uart();
#endif
USART.C 代码
#include
#include
unsigned int buf_num;
bit busy;
u8 rev_buf[6];
void Usart_Int(void)
{
buf_num=0;
ACC = P_SW1;
ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=0
P_SW1 = ACC; //(P3.0/RxD, P3.1/TxD)
#if (PARITYBIT == NONE_PARITY)
SCON = 0x50; //8位可变波特率
#elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
SCON = 0xda; //9位可变波特率,校验位初始为1
#elif (PARITYBIT == SPACE_PARITY)
SCON = 0xd2; //9位可变波特率,校验位初始为0
#endif
T2L = (65536 - (FOSC/4/BAUD)); //设置波特率重装值
T2H = (65536 - (FOSC/4/BAUD))>>8;
AUXR = 0x14; //T2为1T模式, 并启动定时器2
AUXR |= 0x01; //选择定时器2为串口1的波特率发生器
ES = 1; //使能串口1中断
EA = 1;
}
/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4 using 1
{
if (RI)
{
RI = 0; //清除RI位
rev_buf[buf_num] =SBUF;
buf_num ++ ;
}
if (TI)
{
TI = 0; //清除TI位
busy = 0; //清忙标志
}
}
/*----------------------------
发送串口数据
----------------------------*/
void SendData(u8 dat)
{
while (busy); //等待前面的数据发送完成
ACC = dat; //获取校验位P (PSW.0)
if (P) //根据P来设置校验位
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 0; //设置校验位为0
#elif (PARITYBIT == EVEN_PARITY)
TB8 = 1; //设置校验位为1
#endif
}
else
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 1; //设置校验位为1
#elif (PARITYBIT == EVEN_PARITY)
TB8 = 0; //设置校验位为0
#endif
}
busy = 1;
SBUF = ACC; //写数据到UART数据寄存器
}
/*----------------------------
发送字符串
----------------------------*/
void SendString(char *s)
{
while (*s) //检测字符串结束标志
{
SendData(*s++); //发送当前字符
}
}
PWM.H 代码
#ifndef __PWM_H__
#define __PWM_H__
#define PWM_ON 1
#define PWM_OFF (!PWM_ON)
#define Timer0_Rate 25000 //中断频率
#define Timer0_Reload (65536UL -(FOSC / Timer0_Rate)) //Timer 0 重装值
#define PWM_DUTY_MAX 100 // 0~255 PWM周期, 最大255
extern int Red_Value;
extern int Greed_Value;
extern int Blue_Value;
extern int White_Value;
extern int Yellow_Value;
extern int K1_Value;
void Timer0_Int();
#endif
PWM.C 代码
#include
#include
int Red_Value;
int Greed_Value;
int Blue_Value;
int White_Value;
int Yellow_Value;
int K1_Value;
int PWM_COUNT; //PWM计数
void Timer0_Int() //初始化计数器0
{
AUXR |= (1<<7); // Timer0 set as 1T mode
TMOD &= ~(1<<2); // Timer0 set as Timer
TMOD &= ~0x03; // Timer0 set as 16 bits Auto Reload
TH0 = Timer0_Reload / 256; //Timer0 Load
TL0 = Timer0_Reload % 256;
ET0 = 1; //Timer0 Interrupt Enable
PT0 = 0; //高优先级
TR0 = 1; //Timer0 Run
EA = 1; //打开总中断
PWM_COUNT=0;
}
/********************** Timer0 1ms中断函数 ************************/
void timer0 (void) interrupt 1
{
PWM_COUNT++;
if (PWM_COUNT >= PWM_DUTY_MAX)
{
PWM_COUNT =0 ;
RED=PWM_ON;
GREED=PWM_ON;
BLUE=PWM_ON;
WHITE =PWM_ON;
YELLOW =PWM_ON;
K1=PWM_ON;
}
if (Red_Value <= PWM_COUNT) RED = PWM_OFF;
if (Greed_Value <= PWM_COUNT) GREED = PWM_OFF;
if (Blue_Value <= PWM_COUNT) BLUE = PWM_OFF;
if (White_Value <= PWM_COUNT) WHITE = PWM_OFF;
if (Yellow_Value <= PWM_COUNT) YELLOW = PWM_OFF;
if (K1_Value <= PWM_COUNT) K1 = PWM_OFF;
}
MAIN.H 代码
#ifndef __MAIN_H__
#define __MAIN_H__
#include
#define FOSC 11059200L //系统频率
sfr P1M1 = 0x91; //IO模式控制寄存器
sfr P1M0 = 0x92; //IO模式控制寄存器
sfr AUXR = 0x8e; //辅助寄存器
sfr T2H = 0xd6; //定时器2高8位
sfr T2L = 0xd7; //定时器2低8位
sbit RED = P1^1; //RED 接在P1.1 16脚
sbit GREED =P1^3; //GREED 接P1.3 2脚
sbit BLUE =P1^5; //BLUE 接P1.5 4脚
sbit WHITE = P1^2; //白色 接 P1.2 1脚
sbit YELLOW =P1^4; //黄色 接 P1.4 3脚
sbit K1 = P1^0; // P1.0 第15脚 增加多一路当开关使用,同时也支持PWM输出
#endif
MAIN.C 代码
#include
#include
#include
#include
#include
void delay(unsigned int x);
void Act_Bit(void);
extern bit busy;
extern unsigned int buf_num;
extern u8 rev_buf[6];
extern int Red_Value;
extern int Greed_Value;
extern int Blue_Value;
extern int White_Value;
extern int Yellow_Value;
extern int K1_Value;
//按接收到的数据进行处理数据
void Act_Bit(void)
{
//aa f9 01 红 绿 蓝 dd 取值 0~100
//&& rev_buf[1] == 0xf9
if (rev_buf[0] == 0xaa && rev_buf[6] == 0xdd)
{
if (rev_buf[2] == 0x01) //开灯指令
{
if ( rev_buf[1] == 0xf9) //与STM32协议通用,调速RGB 红绿蓝
{
Red_Value= rev_buf[3];
Greed_Value =rev_buf[4];
Blue_Value =rev_buf[5];
}
if ( rev_buf[1] == 0xf8) //增加白色,黄色 PWM控制
{
White_Value = rev_buf[3];
Yellow_Value = rev_buf[4];
K1_Value = rev_buf[5];
}
}
//读取各个PWM值
if (rev_buf[2] == 0xff)
{
SendData(0xff);
SendData(Red_Value);
SendData(Greed_Value);
SendData(Blue_Value);
SendData(White_Value);
SendData(Yellow_Value);
SendData(K1_Value);
}
//对于开关K1,增加协议单独控制
if (rev_buf[1] == 0x00 && rev_buf[2] == 0x00 && rev_buf[3] == 0x00 && rev_buf[4] == 0x00 )
{
Red_Value=0x00;
Greed_Value=0x00 ;
Blue_Value =0x00;
White_Value =0x00;
Yellow_Value=0x00;
if ( rev_buf[5] == 0x00)
{
K1_Value =0x00;
}
}
}
}
void main(void)
{
//P1M1 |= 0x02;
P1M0 |=0x3f; //0x3f; 02 配置IO为推挽输出
Usart_Int();
Timer0_Int();
SendString("STC15F2K60S2\r\nUart Test !\r\n");
while(1)
{
if (buf_num >= DATA_LEN)
{
Act_Bit();
buf_num=0;
}
}
}