目录
简介
本帖原创【禁止转载】,包含PCB图纸及源代码,图纸可直接打板。有不懂的地方先看代码注释,再留言提问。
完整程序点这里,提取码:
PCB文件点这里,提取码:
步骤一 材料准备
硬件准备:
stm8s903k3t6核心板一块
ch340e下载模块一块
stlink v2一块
共阴RGB灯一枚
1K电阻两枚
按键一颗
杜邦线若干根
小面包版两块
软件准备:
STM8版IAR
串口助手SSCOM v5版
步骤二 原理说明
利用人眼视觉暂留效应,调节PWM,变幻出变化的灯光效果。此程序PWM频率为2K,系统时钟为16M, 定时器6频率250k,按键作为外部触发方式,按键上拉。串口用于监视程序执行情况。
按键 PE5
灯光控制1(PWM1) PC1
灯光控制2(PWM2) PC2
灯光控制3(PWM3) PC3
数据发送(RXD ) PD6
数据接收(TXD) PD5
步骤三 电路搭建
按着原理说明连接线路就没问题,或者看程序定义。
步骤四 编写程序
//灯光调节部分
#include "pbdata.h"
u8 rDuty = 255;
u8 gDuty = 0;
u8 bDuty = 0;
u8 flags = 0;
u8 rgbStatus = 1;
u16 Mcolor1 = 100, Mcolor2 = 0; //定义RGB颜色变化的时间长度,每100ms变化一次
u16 nowtime = 0; //获取当前的系统运行时间长度
//开机
void mode_0(void)
{
while (KEY_Demo()==0)
{
SetColor(rDuty,gDuty,bDuty);
delay_ms(5);
switch(flags){
case 0:
gDuty++;
if(gDuty >= 255) flags++;
break;
case 1:
rDuty--;
if(rDuty <= 0) flags++;
break;
case 2:
bDuty++;
if(bDuty >= 255) flags++;
break;
case 3:
gDuty--;
if(gDuty <= 0) flags++;
break;
case 4:
rDuty++;
if(rDuty >= 255) flags++;
break;
case 5:
bDuty--;
if(bDuty <= 0) flags=0;
break;
}
}
}
//模式1_黄光
void mode_1(void)
{
while (KEY_Demo()==1)
{
for (u8 i = 0; i < 255; i++)
{
SetColor(i, i, 0);
delay_ms(13);
}
for (u8 i = 255; i > 0; i--)
{
SetColor(i, i, 0);
delay_ms(13);
}
}
}
//模式2_暖白
void mode_2(void)
{
while (KEY_Demo()==2)
{
SetColor(255, 210, 255);
}
}
//模式3_红光
void mode_3(void)
{
TIM6_Cmd(ENABLE); //开定时器
while (KEY_Demo()==3)
{
UART1_Send_Byte(nowtime);
if (rgbStatus == 1) //Rgb灯的状态切换
{
if (nowtime > Mcolor1) //检测系统运行时间长度是否到100ms
{
Mcolor1 = nowtime; //记录当前时间长度,第一次为100ms,赋值给Mcolor1
Mcolor2 = nowtime + 500; //计算出下一次状态切换的时刻,第一次运行程序时应该在200ms时切换
SetColor(255, 0, 0); // 红色
rgbStatus = 2;
}
}
else
{ //非标志状态Rgb灯的切换
if (nowtime > Mcolor2)
{
Mcolor2 = nowtime;
Mcolor1 = nowtime + 700;
SetColor(0, 0, 0); //关闭
rgbStatus = 1;
}
}
if(nowtime == 30000) nowtime =0;
}
}
//模式4_蓝色
void mode_4(void)
{
while (KEY_Demo()==4)
{
for (u8 i = 0; i < 255; i++)
{
SetColor(0, 0, i);
delay_ms(13);
}
for (u8 i = 255; i > 0; i--)
{
SetColor(0, 0, i);
delay_ms(13);
}
}
}
//模式5_绿色
void mode_5(void)
{
while (KEY_Demo()==5)
{
for (u8 i = 0; i < 255; i++)
{
SetColor(0, i, 0);
delay_ms(13);
}
for (u8 i = 255; i > 0; i--)
{
SetColor(0, i, 0);
delay_ms(13);
}
}
}
//模式6_紫色
void mode_6(void)
{
while (KEY_Demo()==6)
{
SetColor(160, 32, 240); // 紫色
delay_ms(30);
}
}
//模式7_关闭
void mode_7(void)
{
while (KEY_Demo()==7)
{
SetColor(0, 0, 0); // 关闭
delay_ms(10);
}
}
void SetColor(u8 red, u8 green, u8 blue)
{
TIM1_SetCompare1(red);
TIM1_SetCompare2(green);
TIM1_SetCompare3(blue);
}
void loop(void)
{
UART1_Send_Byte(KEY_Demo());
if(KEY_Demo()>7) h=0;
if(KEY_Demo()==0)
{
UART1_Send_Byte(h);mode_0();
}
else if(KEY_Demo()==1)
{
UART1_Send_Byte(h);mode_1();
}
else if(KEY_Demo()==2)
{
UART1_Send_Byte(h);mode_2();
}
else if(KEY_Demo()==3)
{
UART1_Send_Byte(h); mode_3();
}
else if(KEY_Demo()==4)
{
UART1_Send_Byte(h);mode_4();
}
else if(KEY_Demo()==5)
{
UART1_Send_Byte(h);mode_5();
}
else if(KEY_Demo()==6)
{
UART1_Send_Byte(h);mode_6();
}
else if(KEY_Demo()==7)
{
UART1_Send_Byte(h);mode_7();
}
}
//按键部分
#include "pbdata.h"
u8 h=0;
/*********************************************************************************
* 函 数 名: KEY_Init
* 功能说明: KEY的GPIO管脚初始化
* 形 参:无
* 返 回 值: 无
*********************************************************************************/
void Key_Init(void)
{
GPIO_Init(TOUCH_PORT, TOUCH_PIN, GPIO_MODE_IN_PU_IT);//上拉中断
EXTI_SetExtIntSensitivity(TOUCH_EXIT_PORT, EXTI_SENSITIVITY_FALL_ONLY);//下降沿中断
ITC_SetSoftwarePriority(ITC_IRQ_PORTE, ITC_PRIORITYLEVEL_3);//优先级2
}
/*********************************************************************************
* 函 数 名: KEY_Down
* 功能说明: 键盘检测消斗
* 形 参:GPIO_TypeDef* GPIOx 输入要检测的端口
* GPIO_Pin_TypeDef GPIO_Pin 输入要检测的引脚
* 返 回 值: 布尔类型 (true 按下,flase 弹起)
*********************************************************************************/
bool KEY_Down(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin)
{
//检测是否有按键按下
if(GPIO_ReadInputPin(GPIOx,GPIO_Pin)==0)//是否为低电平,低电平按下,高电平弹起
{
delay_ms(20);//延时20毫秒消抖
if(GPIO_ReadInputPin(GPIOx,GPIO_Pin)==0)//再一次检测键盘是否有按下
{
//低电平为真(等待) 高电平为假(退出WHILE循环)
while(GPIO_ReadInputPin(GPIOx,GPIO_Pin)==0);
return true;//函数返回真
}
}
return false;//函数返回假
}
/*********************************************************************************
* 函 数 名: KEY_Demo
* 功能说明: 键盘输入检测
* 形 参:无
* 返 回 值: 无
*********************************************************************************/
u8 KEY_Demo(void)
{
if(KEY_Down(TOUCH_PORT, TOUCH_PIN)==true)//判断TOUCH触摸键盘是否被按下,如果按下将执行下面的语句,否则退出函数。
{
h++;
//UART1_Send_Byte(h);
}
delay_ms(20);
//UART1_Send_Byte(h);
return h;
}
//定时器一
#include "pbdata.h"
/*********************************************************************************
* 函 数 名: Tim1_PWM_Init
* 功能说明: 初始化高级定时器1
* 形 参:无
* 返 回 值: 无
*********************************************************************************/
void Tim1_PWMInit(void)//初始化TIM1时基单元
{
TIM1_TimeBaseInit(31, TIM1_COUNTERMODE_UP, 255, 0); //16M/32=500K(2US) 2*256=512US(~2KHZ)
TIM1_ARRPreloadConfig(ENABLE);//使能自动重装
//初始化俘获/比较通道一
TIM1_OC1Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_ENABLE, 0, TIM1_OCPOLARITY_LOW, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_RESET);
//初始化俘获/比较通道二
TIM1_OC2Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, 0, TIM1_OCPOLARITY_LOW, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_RESET);
//初始化俘获/比较通道三
TIM1_OC3Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, 0, TIM1_OCPOLARITY_LOW, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_RESET);
//初始化俘获/比较通道四
//TIM1_OC4Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, 0, TIM1_OCPOLARITY_HIGH, TIM1_OCIDLESTATE_RESET);
TIM1_Cmd(ENABLE);
TIM1_CtrlPWMOutputs(ENABLE);
}
//串口
#include "pbdata.h"
/*********************************************************************************
* 函 数 名: UART1_Congfiguration
* 功能说明: UART1 配置函数
* 形 参:无
* 返 回 值: 无
*********************************************************************************/
void Uart1_Congfiguration(void)
{
UART1_Init((u32)115200, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
// UART1_Init((u32)9600, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
UART1_Cmd(ENABLE);
UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);
}
/*********************************************************************************
* 函 数 名: UART1_Send_Byte
* 功能说明: UART1发送数据函数
* 形 参:u8 byte 一次发送一个字节
* 返 回 值: 无
*********************************************************************************/
void UART1_Send_Byte(u8 byte)
{
UART1_SendData8(byte);//UART1发送8位数据
while(UART1_GetFlagStatus(UART1_FLAG_TXE)==RESET);//等待发送完成
}
//定时器6
#include "pbdata.h"
u8 Tim6_Upd_n=0;
/*********************************************************************************
* 函 数 名: Tim6_Init
* 功能说明: 初始化通用定时器6
* 形 参:无
* 返 回 值: 无
*********************************************************************************/
void Tim6_Init(void)
{
TIM6_TimeBaseInit(TIM6_PRESCALER_64, 250);//初始化定时器6 2M/8=250k 4us 4*250=1000us(1ms)
TIM6_ARRPreloadConfig(ENABLE);//使能自动重装 16M/64=250k
TIM6_ITConfig(TIM6_IT_UPDATE, ENABLE);//数据更新中断
}
/*********************************************************************************
* 函 数 名: Tim6_Upd
* 功能说明: Tim6精准延时函数计数
* 形 参:无
* 返 回 值: 无
*********************************************************************************/
void Tim6_Upd(void)
{
if(Tim6_Upd_n!=0)
{
Tim6_Upd_n--;
}
}
/*********************************************************************************
* 函 数 名: Tim6_ms
* 功能说明: Tim6精准延时函数
* 形 参:u16 nTime 输入1为1个毫秒
* 返 回 值: 无
*********************************************************************************/
void Tim6_ms(u16 nTime)
{
Tim6_Upd_n=nTime;
while(Tim6_Upd_n!=0);//延时等待 当Tim6_Upd_n=0时退出while循环
}
步骤五 验证结果
视频上传太麻烦了,不能直接录制上传,在这里我用图片代替吧。按切换按键可以切换闪烁状态,完成了本项目的要求!