aming_ou 发表于 2025-9-18 11:32:03

哪位大神有STC8G1K08A 解码 VS1838 红外遥控信号并打印到串口的Keil程序

哪位大神有STC8G1K08A 解码 VS1838 红外遥控信号并打印到串口的源代码?

网上找了很久,也问DS了,拿到的源代码,编译通过,但串口没有打印红外遥控的数据

STC8G1K08A引脚连接说明:

5,P3.0,RxD
6,P3.1,Txd
7,P3.2,IR红外接收管VS1838B 信号输入
8,P3.3,连接LED+,作为状态指示,上电常亮,接收并解码到遥控器(例如电视)数据后闪烁。

研究过程:
使用 STC8G-STC8H-LIB-DEMO-CODE\独立程序\05-串口1中断模式与电脑收发测试\ 的工程文件,编译下载,串口工具能发送和接收。

DS 提供的代码,并补全端口初始化代码,编译成功,商店指示灯常亮,但按电视遥控器按键时,串口没有打印数据。

//#include <STC8G.H>
//#include <intrins.h>
#include        "config.h"

#define FOSC 11059200UL      // 系统频率
#define BAUDRATE 9600UL      // 串口波特率

// 红外接收引脚定义
sbit IR_IN = P3^2;         // 使用INT0引脚(P3.2)接收红外信号
sbit LED = P3^3;             // 使用INT0引脚(P3.3)连接指示灯

// 全局变量
unsigned char irCode;   // 存储解码后的4字节数据
bit irFlag = 0;            // 红外解码完成标志

// 函数声明
void PORT_Init(void);
void UART_Init(void);
void UART_SendByte(unsigned char dat);
void UART_SendString(char *s);
void IR_Init(void);
void IR_Decode(void);
void Delay10us(unsigned int n);
void Delay100ms(unsigned int n)


// 端口初始化
void PORT_Init(void)
{
    P3M0 = (P3M0 & ~0x04) | 0x08; P3M1 = (P3M1 & ~0x08) | 0x04;
        P3INTE = 0x04;                        //使能P3口中断
        P3IM0 = 0x00;                        //设置P3口中断模式 (00:下降沿, 01:上升沿)
        P3IM1 = 0x00;                        //设置P3口中断模式 (10:低电平, 11:高电平)
        P3WKUE = 0x00;                        //设置P3口中断唤醒省电模式

}
// 串口初始化
void UART_Init(void)
{
    SCON = 0x50;            // 8位数据,可变波特率
    AUXR |= 0x40;         // 定时器1时钟为Fosc,即1T
    AUXR &= 0xFE;         // 串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;         // 清除定时器1模式位
    TMOD |= 0x20;         // 设定定时器1为8位自动重装方式
    TL1 = 0xFC;             // 设定定时初值
    TH1 = 0xFC;             // 设定定时器重装值
    ET1 = 0;                // 禁止定时器1中断
    TR1 = 1;                // 启动定时器1
}


// 发送一个字节
void UART_SendByte(unsigned char dat)
{
    SBUF = dat;
    while(TI == 0);
    TI = 0;
}

// 发送字符串
void UART_SendString(char *s)
{
    while(*s != '\0')
    {
      UART_SendByte(*s++);
    }
}

// 红外初始化
void IR_Init(void)
{
    IT0 = 1;                // 设置INT0下降沿触发
    EX0 = 1;                // 使能INT0中断
    EA = 1;               // 开启总中断
    IR_IN = 1;            // 设置红外接收引脚为输入模式
}

// 10us延时函数
void Delay10us(unsigned int n)
{
    while(n--)
    {
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
    }
}

void Delay100ms(unsigned int n)        //@11.0592MHz
{
        unsigned char data i, j, k;
    while(n--)
                {
                i = 5;
                j = 52;
                k = 195;
                do
                {
                        do
                        {
                                while (--k);
                        } while (--j);
                } while (--i);
    }
}


// INT0中断服务函数 - 红外解码
void INT0_ISR() interrupt 0
{
    unsigned char i, j;
    unsigned char byte;
    unsigned int time;
   
    // 等待起始信号9ms低电平
    while(IR_IN == 0);
   
    // 检测4.5ms高电平
    time = 0;
    while(IR_IN == 1)
    {
      Delay10us(1);
      time++;
      if(time > 500)      // 超过5ms退出,防止死循环
            return;
    }
   
    // 开始解码4字节数据
    for(i = 0; i < 4; i++)
    {
      byte = 0;
      for(j = 0; j < 8; j++)
      {
            // 等待低电平结束
            while(IR_IN == 0);
            
            // 计算高电平持续时间
            time = 0;
            while(IR_IN == 1)
            {
                Delay10us(1);
                time++;
                if(time > 100)// 超过1ms退出
                  break;
            }
            
            // 判断数据位是0还是1
            if(time > 8)      // 高电平时间大于560us为1
                byte |= 0x80 >> j;
      }
      irCode = byte;
    }
   
    irFlag = 1;             // 设置解码完成标志
}

// 主函数
void main(void)
{
    unsigned char i;
    char buffer;
   
    // 初始化
        PORT_Init();
    UART_Init();
    IR_Init();
    LED = 1;
       
    UART_SendString("STC8G1K08A IR Decoder Ready!\r\n");
    while(1)
    {
      if(irFlag)          // 如果红外解码完成
      {
            irFlag = 0;   // 清除标志
            
            // 通过串口发送解码结果
            UART_SendString("IR Code: ");
            
            for(i = 0; i < 4; i++)
            {
                // 将字节转换为十六进制字符串
                sprintf(buffer, "%02X ", irCode);
                UART_SendString(buffer);
            }
            UART_SendString("\r\n");
            
            // 显示用户码和键值码
            sprintf(buffer, "User: %02X%02X ", irCode, irCode);
            UART_SendString(buffer);
            
            sprintf(buffer, "Key: %02X\r\n", irCode);
            UART_SendString(buffer);
                        LED = !LED;
                        Delay100ms(5);
                        LED = !LED;
                       
      }
    }
}

国芯人工智能 发表于 2025-9-18 11:33:06

当然可以,以下是一份适用于 STC8G1K08A 单片机,使用 Keil C51 编译器,通过 红外接收头 VS1838B 解码 NEC 格式红外遥控信号,并通过串口 1 打印解码结果的完整源代码。该程序基于标准 NEC 红外协议进行解码,适用于常见的电视、空调等遥控器。

✅ 一、硬件连接说明(与你描述一致)

| 引脚 | 功能         | 连接设备       |
|------|----------------|----------------|
| P30| UART RXD       | 串口接收       |
| P31| UART TXD       | 串口发送       |
| P32| IRIN (INT0)   | VS1838B 输出   |
| P33| LED            | 状态指示灯   |

✅ 二、红外协议说明(NEC 协议)

NEC 红外协议是目前最通用的红外遥控协议之一,其主要特征如下:
起始码:9ms 低电平 + 4.5ms 高电平
数据位:32 位(地址 + 地址反码 + 命令 + 命令反码)
每位传输时间:
0:560μs 低 + 560μs 高
1:560μs 低 + 1680μs 高
载波频率:38kHz

本程序采用 外部中断 0 (INT0) 捕获红外信号,并使用 定时器 0 测量高低电平持续时间,完成解码。

✅ 三、完整 Keil C51 源代码

```c
include

define FOSC 11059200UL
define BAUD 9600

sbit IRIN = P3^2;// 红外接收引脚
sbit LED = P3^3;    // 指示灯

unsigned char ircode;// 存储接收到的4字节数据
bit irdecodecomplete = 0;

unsigned char bitcount = 0;
unsigned long irtime = 0;
unsigned long irprevtime = 0;
unsigned char irstate = 0;

void UARTInit(void) {
    SCON = 0x50;            // 8位异步串口,允许接收
    AUXR |= 0x01;         // 定时器1为1T模式
    TMOD &= 0x0F;
    TMOD |= 0x20;         // 定时器1,模式2(8位自动重装)
    TH1 = TL1 = (256 - (FOSC / 12 / 32 / BAUD));
    TR1 = 1;                // 启动定时器1
    ES = 1;               // 使能串口中断
    EA = 1;
}

void SendChar(char c) {
    SBUF = c;
    while (!TI); TI = 0;
}

void SendString(char s) {
    while (s) {
      SendChar(s++);
    }
}

void SendHexByte(unsigned char b) {
    unsigned char hi = (b >> 4) & 0x0F;
    unsigned char lo = b & 0x0F;
    SendChar(hi < 10 ? '0' + hi : 'A' + hi - 10);
    SendChar(lo < 10 ? '0' + lo : 'A' + lo - 10);
}

void PORTInit(void) {
    P3M0 = 0x00;
    P3M1 = 0x00;// P3 全部设为推挽输出
    IRIN = 1;    // 设置为输入
}

void Timer0Init(void) {
    TMOD |= 0x02;// 定时器0模式2(8位自动重装)
    TH0 = 0x00;
    TL0 = 0x00;
    TR0 = 1;       // 启动定时器0
}

void IRInterruptInit(void) {
    IT0 = 1;       // 下降沿触发
    EX0 = 1;       // 使能INT0中断
    EA = 1;
}

void IRProcess(void) {
    unsigned long duration = irtime;
    switch (irstate) {
      case 0:// 等待起始码低电平(9ms)
            if (duration > 8000 && duration < 10000) {
                irstate++;
            } else {
                irstate = 0;
            }
            break;
      case 1:// 等待起始码高电平(4.5ms)
            if (duration > 3500 && duration < 5500) {
                bitcount = 0;
                irstate++;
            } else {
                irstate = 0;
            }
            break;
      case 2:// 接收32位数据
            if (duration > 1000 && duration < 2000) {
                // 1
                ircode |= (1400 && duration < 800) {
                // 0
                // ircode &= ~(1

[本文内容由国芯人工智能辅助生成,仅供参考]

DebugLab 发表于 2025-9-18 22:04:08

几年前写的15W系列解码38K NEC协议红外遥控12864液晶屏程序供参考:
串口程序参考:https://www.stcaimcu.com/thread-16321-1-1.html
#include <STC15F2K60S2.H>
#include <intrins.h>
#define                RXD                              P30
#define                TXD                              P31
#define                IRIN                        P32
#define         Buzzer                        P33                        //定义蜂鸣器IO口
#define         LCD12864_SID      P34                        //定义LCD12864时钟IO口
#define         LCD12864_SCLK      P35                        //定义LCD12864数据IO口
#define         Write_Command                                                                        0xf8
#define         Write_Data                                                                              0xfa
#define         Read_Command                                                                        0xfc
#define                Read_Data                                                                              0xfe
#define                Setting_Basic_Instruction_Set                                        0x30
#define                Setting_Extended_Instruction_Set_Drawing_Off      0x34
#define                Setting_Extended_Instruction_Set_Drawing_On                0x36
#define                Clear_Display                                                                        0x01
#define                Entry_Mode_Cursor_Left                                                      0x04
#define                Entry_Mode_Entire_Right                                                      0x05
#define                Entry_Mode_Cursor_Right                                                      0x06
#define                Entry_Mode_Entire_Left                                                      0x07
#define                Display_Off                                                                              0x08
#define                Display_On_Cursor_Off_Inverse_Off                              0x0c
#define                Display_On_Cursor_Off_Inverse_On                              0x0d
#define                Display_On_Cursor_On_Inverse_Off                              0x0e
#define                Display_On_Cursor_On_Inverse_On                                        0x0f
#define                Cursor_Move_Left                                                                0x10
#define                Cursor_Move_Right                                                                0x14
#define                Display_Move_Left                                                                0x18
#define                Display_Move_Right                                                                0x1c
bit Error_Flag;
unsigned char ms_50,Temp_Second,Temp;
unsigned char IRCOM;
unsigned char code Display_Hex={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};
unsigned char code Display_Data1=
{
      "红外遥控解码"      //0x80
      "    IR_Code:    "      //0x90
      "                "      //0x88
      "                "      //0x98
};

/*----------------------------延时10us@STC-Y5@11.0592MHz----------------------------*/
void Delay_10us(void)
{
      unsigned char i;
      _nop_();
      _nop_();
      i=25;
      while(--i);
}

/*----------------------------延时x10us----------------------------*/
void Delay_x10us(unsigned char x)
{
      while(x--)
                Delay_10us();
}

/*----------------------------延时10ms@STC-Y5@11.0592MHz----------------------------*/
void Delay_10ms(void)
{
      unsigned char i,j;
      i=108;
      j=145;
      do
      {
                while(--j);
      }while(--i);
}

/*----------------------------延时140us@STC-Y5@11.0592MHz----------------------------*/
void Delay_140us(void)
{
      unsigned char i,j;
      i=2;
      j=126;
      do
      {
                while(--j);
      }
      while(--i);
}

void Delay_x140us(unsigned char x)
{
      while(x--)
                Delay_140us();
}

/*----------------------------写1字节命令或数据----------------------------*/
void LCD12864_Write_Byte(unsigned char temp)
{
      unsigned char i;
      for(i=0;i<8;i++)
      {
                if((temp<<i)&0x80)
                        LCD12864_SID=1;
                else
                        LCD12864_SID=0;
                LCD12864_SCLK=0;
                LCD12864_SCLK=1;
      }
}

/*----------------------------传送数据或者命令----------------------------*/
void LCD12864_Write(unsigned char Command,unsigned char temp)
{
      LCD12864_Write_Byte(Command);
      LCD12864_Write_Byte(temp&0xf0);
      LCD12864_Write_Byte((temp<<4)&0xf0);
}

/*----------------------------清空GDRAM----------------------------*/
void Clear_GDRAM(void)
{
      unsigned char i,j,k;
      LCD12864_Write(Write_Command,Setting_Extended_Instruction_Set_Drawing_Off);
      k=0x80;
      for(i=0;i<32;i++)
      {
                LCD12864_Write(Write_Command,k++);
                LCD12864_Write(Write_Command,0x80);
                for(j=0;j<16;j++)
                {
                        LCD12864_Write(Write_Data,0x00);
                }
      }
      k=0x80;
      for(i=0;i<32;i++)
      {
                LCD12864_Write(Write_Command,k++);
                LCD12864_Write(Write_Command,0x88);
                for(j=0;j<16;j++)
                {
                        LCD12864_Write(Write_Data,0x00);
                }
      }
      LCD12864_Write(Write_Command,Setting_Extended_Instruction_Set_Drawing_On);
}

/*----------------------------整页显示字符----------------------------*/
void Display_Text(unsigned char code *addr)
{
      unsigned char i;
      LCD12864_Write(Write_Command,Setting_Basic_Instruction_Set);
      LCD12864_Write(Write_Command,0x80);      //设置DDRAM地址
      Delay_10us();
      for(i=0;i<16;i++)
      {
                LCD12864_Write(Write_Data,*addr);
                addr++;
      }
      LCD12864_Write(Write_Command,0x90);      //设置DDRAM地址
      Delay_10us();
      for(i=0;i<16;i++)
      {
                LCD12864_Write(Write_Data,*addr);
                addr++;
      }
      LCD12864_Write(Write_Command,0x88);      //设置DDRAM地址
      Delay_10us();
      for(i=0;i<16;i++)
      {
                  LCD12864_Write(Write_Data,*addr);
                addr++;
      }
      LCD12864_Write(Write_Command,0x98);      //设置DDRAM地址
      Delay_10us();
      for(i=0;i<16;i++)
      {
                LCD12864_Write(Write_Data,*addr);
                addr++;
      }
}

/*----------------------------指定位置显示字符----------------------------*/
void Display_Data(unsigned char x,unsigned char y,unsigned char Data1,unsigned char Data2)
{
      LCD12864_Write(Write_Command,Setting_Basic_Instruction_Set);
      switch(y)
      {
                case 0:
                        LCD12864_Write(Write_Command,0x80+x);      //设置DDRAM地址
                        Delay_10us();
                        LCD12864_Write(Write_Data,Data1);
                        LCD12864_Write(Write_Data,Data2);
                        break;
                case 1:
                        LCD12864_Write(Write_Command,0x90+x);      //设置DDRAM地址
                        Delay_10us();
                        LCD12864_Write(Write_Data,Data1);
                        LCD12864_Write(Write_Data,Data2);
                        break;
                case 2:
                        LCD12864_Write(Write_Command,0x88+x);      //设置DDRAM地址
                        Delay_10us();
                        LCD12864_Write(Write_Data,Data1);
                        LCD12864_Write(Write_Data,Data2);
                        break;
                case 3:
                        LCD12864_Write(Write_Command,0x98+x);      //设置DDRAM地址
                        Delay_10us();
                        LCD12864_Write(Write_Data,Data1);
                        LCD12864_Write(Write_Data,Data2);
                        break;
      }
}

/*----------------------------初始化12864----------------------------*/
void LCD12864_Init(void)
{
      Delay_10ms();                        //40mS延时
      Delay_10ms();
      Delay_10ms();
      Delay_10ms();
      LCD12864_Write(Write_Command,Setting_Basic_Instruction_Set);
      Delay_x10us(10);                //100uS延时
      LCD12864_Write(Write_Command,Setting_Basic_Instruction_Set);
      Delay_x10us(4);                        //40uS延时
      LCD12864_Write(Write_Command,Clear_Display);      //显示光标闪烁完全关闭
      Delay_x10us(10);                //100uS延时
      LCD12864_Write(Write_Command,Clear_Display);                                                //清除显示
      Delay_10ms();                        //10mS延时
      LCD12864_Write(Write_Command,Entry_Mode_Cursor_Right);                              //光标右移模式
      Delay_x10us(10);                //100uS延时
      LCD12864_Write(Write_Command,Display_On_Cursor_Off_Inverse_Off);      //开显示,无光标,光标不闪烁
      Delay_x10us(10);                //100uS延时
      Clear_GDRAM();                        //清空GDRAM
      Delay_x10us(10);                //100uS延时
}

void Init(void)
{
      P3M0=0x08;
      P3M1=0x00;
      IRIN=1;      
      EA=1;
      EX0=1;
      IT0=1;
      Buzzer=0;
      LCD12864_Init();
}

/*----------------------------主函数----------------------------*/
void main(void)
{
      Init();
      Display_Text(Display_Data1);
      while(1)
                if(RXD==0)
                        IAP_CONTR=0x60;
}

void IR_IN(void) interrupt 0
{
      unsigned char j,k,n=0,q=0;
      EX0=0;
      Delay_x140us(15);
      if(IRIN==1)
      {
                EX0=1;
                return;
      }
      while(!IRIN)
                Delay_x140us(1);
      for(j=0;j<4;j++)
      {
                for(k=0;k<8;k++)
                {
                        while(IRIN)
                              Delay_x140us(1);
                        while(!IRIN)
                              Delay_x140us(1);
                        while(IRIN)
                        {
                              Delay_x140us(1);
                              n++;
                              if(n>=30)
                              {
                                        EX0=1;
                                        return;
                              }
                        }
                        IRCOM=IRCOM>>1;
                        if(n>=8)
                        {
                              IRCOM=IRCOM|0x80;
                        }
                        n=0;
                }
      }
      if(IRCOM!=~IRCOM)
      {
                EX0=1;
                return;
      }
      else
      {
                Display_Data(1,2,Display_Hex/16],Display_Hex%16]);
                Display_Data(2,2,Display_Hex/16],Display_Hex%16]);
                Display_Data(3,2,Display_Hex/16],Display_Hex%16]);
                Display_Data(4,2,Display_Hex/16],Display_Hex%16]);
                Display_Data(6,2,Display_Hex/16],Display_Hex%16]);
                Buzzer=1;
                Delay_10ms();
                Buzzer=0;
      }
      EX0=1;
}

aming_ou 发表于 2025-9-19 00:20:06

国芯人工智能 发表于 2025-9-18 11:33
当然可以,以下是一份适用于 STC8G1K08A 单片机,使用 Keil C51 编译器,通过 红外接收头 VS1838B 解码 NEC ...

请问kimi还是deepseek自动生成的c代码吗? 代码不完整,可以提供完整的代码吗?最好上传附件

aming_ou 发表于 2025-9-19 00:22:01

DebugLab 发表于 2025-9-18 22:04
几年前写的15W系列解码38K NEC协议红外遥控12864液晶屏程序供参考:
串口程序参考:https://www.stcaimcu.c ...

看文件头的配置,

aming_ou 发表于 2025-9-19 00:25:11

DebugLab 发表于 2025-9-18 22:04
几年前写的15W系列解码38K NEC协议红外遥控12864液晶屏程序供参考:
串口程序参考:https://www.stcaimcu.c ...

看文件头的定义,管脚只用这几个,应该使用于STC8G1K08A ,多谢大神,我先学习研究下,看能不能转为打印到串口工具窗口,而不使用显示屏
#include <STC15F2K60S2.H>
#include <intrins.h>
#define                RXD                              P30
#define                TXD                              P31
#define                IRIN                        P32
#define         Buzzer                        P33   

aming_ou 发表于 2025-9-19 00:54:36

DebugLab 发表于 2025-9-18 22:04
几年前写的15W系列解码38K NEC协议红外遥控12864液晶屏程序供参考:
串口程序参考:https://www.stcaimcu.c ...

找了一片oled 12864的,然后再看代码时,才发现STC8G1K08A没有P34和P35 GPIO,按引脚说明,P34 ~~P33,而P35~~P32,这样就无法用P32做IRIN,如果把IRIN改到P55,又无法直接编译你的代码进行下载测试。
#define LCD12864_SIDP34 //定义LCD12864时钟IO口
#define LCD12864_SCLK P35 //定义LCD12864数据IO口
页: [1]
查看完整版本: 哪位大神有STC8G1K08A 解码 VS1838 红外遥控信号并打印到串口的Keil程序