找回密码
 立即注册
查看: 10|回复: 1

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

[复制链接]
  • 打卡等级:常住居民II
  • 打卡总天数:99
  • 最近打卡:2025-09-18 10:31:49
已绑定手机

5

主题

16

回帖

438

积分

中级会员

积分
438
发表于 6 小时前 | 显示全部楼层 |阅读模式
哪位大神有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 提供的代码,并补全端口初始化代码,编译成功,商店指示灯常亮,但按电视遥控器按键时,串口没有打印数据。

  1. //#include <STC8G.H>
  2. //#include <intrins.h>
  3. #include        "config.h"
  4. #define FOSC 11059200UL      // 系统频率
  5. #define BAUDRATE 9600UL      // 串口波特率
  6. // 红外接收引脚定义
  7. sbit IR_IN = P3^2;           // 使用INT0引脚(P3.2)接收红外信号
  8. sbit LED = P3^3;             // 使用INT0引脚(P3.3)连接指示灯
  9. // 全局变量
  10. unsigned char irCode[4];     // 存储解码后的4字节数据
  11. bit irFlag = 0;              // 红外解码完成标志
  12. // 函数声明
  13. void PORT_Init(void);
  14. void UART_Init(void);
  15. void UART_SendByte(unsigned char dat);
  16. void UART_SendString(char *s);
  17. void IR_Init(void);
  18. void IR_Decode(void);
  19. void Delay10us(unsigned int n);
  20. void Delay100ms(unsigned int n)
  21. // 端口初始化
  22. void PORT_Init(void)
  23. {
  24.     P3M0 = (P3M0 & ~0x04) | 0x08; P3M1 = (P3M1 & ~0x08) | 0x04;
  25.         P3INTE = 0x04;                        //使能P3口中断
  26.         P3IM0 = 0x00;                        //设置P3口中断模式 (00:下降沿, 01:上升沿)
  27.         P3IM1 = 0x00;                        //设置P3口中断模式 (10:低电平, 11:高电平)
  28.         P3WKUE = 0x00;                        //设置P3口中断唤醒省电模式
  29. }
  30. // 串口初始化
  31. void UART_Init(void)
  32. {
  33.     SCON = 0x50;            // 8位数据,可变波特率
  34.     AUXR |= 0x40;           // 定时器1时钟为Fosc,即1T
  35.     AUXR &= 0xFE;           // 串口1选择定时器1为波特率发生器
  36.     TMOD &= 0x0F;           // 清除定时器1模式位
  37.     TMOD |= 0x20;           // 设定定时器1为8位自动重装方式
  38.     TL1 = 0xFC;             // 设定定时初值
  39.     TH1 = 0xFC;             // 设定定时器重装值
  40.     ET1 = 0;                // 禁止定时器1中断
  41.     TR1 = 1;                // 启动定时器1
  42. }
  43. // 发送一个字节
  44. void UART_SendByte(unsigned char dat)
  45. {
  46.     SBUF = dat;
  47.     while(TI == 0);
  48.     TI = 0;
  49. }
  50. // 发送字符串
  51. void UART_SendString(char *s)
  52. {
  53.     while(*s != '\0')
  54.     {
  55.         UART_SendByte(*s++);
  56.     }
  57. }
  58. // 红外初始化
  59. void IR_Init(void)
  60. {
  61.     IT0 = 1;                // 设置INT0下降沿触发
  62.     EX0 = 1;                // 使能INT0中断
  63.     EA = 1;                 // 开启总中断
  64.     IR_IN = 1;              // 设置红外接收引脚为输入模式
  65. }
  66. // 10us延时函数
  67. void Delay10us(unsigned int n)
  68. {
  69.     while(n--)
  70.     {
  71.         _nop_();
  72.         _nop_();
  73.         _nop_();
  74.         _nop_();
  75.         _nop_();
  76.     }
  77. }
  78. void Delay100ms(unsigned int n)        //@11.0592MHz
  79. {
  80.         unsigned char data i, j, k;
  81.     while(n--)
  82.                 {
  83.                 i = 5;
  84.                 j = 52;
  85.                 k = 195;
  86.                 do
  87.                 {
  88.                         do
  89.                         {
  90.                                 while (--k);
  91.                         } while (--j);
  92.                 } while (--i);
  93.     }
  94. }
  95. // INT0中断服务函数 - 红外解码
  96. void INT0_ISR() interrupt 0
  97. {
  98.     unsigned char i, j;
  99.     unsigned char byte;
  100.     unsigned int time;
  101.    
  102.     // 等待起始信号9ms低电平
  103.     while(IR_IN == 0);
  104.    
  105.     // 检测4.5ms高电平
  106.     time = 0;
  107.     while(IR_IN == 1)
  108.     {
  109.         Delay10us(1);
  110.         time++;
  111.         if(time > 500)      // 超过5ms退出,防止死循环
  112.             return;
  113.     }
  114.    
  115.     // 开始解码4字节数据
  116.     for(i = 0; i < 4; i++)
  117.     {
  118.         byte = 0;
  119.         for(j = 0; j < 8; j++)
  120.         {
  121.             // 等待低电平结束
  122.             while(IR_IN == 0);
  123.             
  124.             // 计算高电平持续时间
  125.             time = 0;
  126.             while(IR_IN == 1)
  127.             {
  128.                 Delay10us(1);
  129.                 time++;
  130.                 if(time > 100)  // 超过1ms退出
  131.                     break;
  132.             }
  133.             
  134.             // 判断数据位是0还是1
  135.             if(time > 8)        // 高电平时间大于560us为1
  136.                 byte |= 0x80 >> j;
  137.         }
  138.         irCode[i] = byte;
  139.     }
  140.    
  141.     irFlag = 1;             // 设置解码完成标志
  142. }
  143. // 主函数
  144. void main(void)
  145. {
  146.     unsigned char i;
  147.     char buffer[10];
  148.    
  149.     // 初始化
  150.         PORT_Init();
  151.     UART_Init();
  152.     IR_Init();
  153.     LED = 1;
  154.        
  155.     UART_SendString("STC8G1K08A IR Decoder Ready!\r\n");
  156.     while(1)
  157.     {
  158.         if(irFlag)          // 如果红外解码完成
  159.         {
  160.             irFlag = 0;     // 清除标志
  161.             
  162.             // 通过串口发送解码结果
  163.             UART_SendString("IR Code: ");
  164.             
  165.             for(i = 0; i < 4; i++)
  166.             {
  167.                 // 将字节转换为十六进制字符串
  168.                 sprintf(buffer, "%02X ", irCode[i]);
  169.                 UART_SendString(buffer);
  170.             }
  171.             UART_SendString("\r\n");
  172.             
  173.             // 显示用户码和键值码
  174.             sprintf(buffer, "User: %02X%02X ", irCode[0], irCode[1]);
  175.             UART_SendString(buffer);
  176.             
  177.             sprintf(buffer, "Key: %02X\r\n", irCode[2]);
  178.             UART_SendString(buffer);
  179.                         LED = !LED;
  180.                         Delay100ms(5);
  181.                         LED = !LED;
  182.                        
  183.         }
  184.     }
  185. }
复制代码


回复

使用道具 举报 送花

3

主题

1967

回帖

782

积分

等待验证会员

积分
782
发表于 6 小时前 | 显示全部楼层
当然可以,以下是一份适用于 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];  // 存储接收到的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[bitcount / 8] |= (1  400 && duration < 800) {
                // 0
                // ircode[bitcount / 8] &= ~(1

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

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-9-18 17:34 , Processed in 0.117760 second(s), 53 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表