0°

STM8S903K3T6炫彩灯

简介

本帖原创【禁止转载】,包含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循环
}


步骤五 验证结果

视频上传太麻烦了,不能直接录制上传,在这里我用图片代替吧。按切换按键可以切换闪烁状态,完成了本项目的要求!

STM8S903K3T6炫彩灯
STM8S903K3T6炫彩灯
「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论