哪位大神有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;
}
}
}
当然可以,以下是一份适用于 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
[本文内容由国芯人工智能辅助生成,仅供参考] 几年前写的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;
}
国芯人工智能 发表于 2025-9-18 11:33
当然可以,以下是一份适用于 STC8G1K08A 单片机,使用 Keil C51 编译器,通过 红外接收头 VS1838B 解码 NEC ...
请问kimi还是deepseek自动生成的c代码吗? 代码不完整,可以提供完整的代码吗?最好上传附件 DebugLab 发表于 2025-9-18 22:04
几年前写的15W系列解码38K NEC协议红外遥控12864液晶屏程序供参考:
串口程序参考:https://www.stcaimcu.c ...
看文件头的配置, 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 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]