新手,isp串口助手接收不到数据 | 已给串口1的参考程序,波特率公式用新的
芯片型号IAP15F2K61S2,程序见下,按下s1,计数功能正常,
按下s2发送数据,串口接收缓存区无显示,
重新按下s1,计数功能不工作,请问如何解决
ORG 0000H
LJMP MAIN
ORG 0100H
MAIN:
MOV SP, #70H ; 设置堆栈指针
ACALL INIT_UART ; 初始化串口
MOV R5, #0 ; 初始化计数器
ACALL DISPLAY ; 初始显示00
MAIN_LOOP:
ACALL KEY_SCAN ; 扫描按键
SJMP MAIN_LOOP ; 主循环
INIT_UART:
ANL PCON, #7FH ; 波特率不倍速 (SMOD=0)
MOV TMOD, #20H ; 定时器1模式2 (自动重装)
MOV TH1, #0FDH ; 波特率9600 (11.0592MHz晶振)
MOV TL1, #0FDH
SETB TR1 ; 启动定时器1
MOV SCON, #50H ; 串口模式1,允许接收
CLR TI ; 清除发送中断标志
RET
; 数码管显示
DISPLAY:
MOV A, R5 ; 读取计数值
MOV B, #10 ; 除以10分离十位和个位
DIV AB
MOV R6, A
MOV R7, B
; P0显示十位
MOV DPTR, #TABA
MOV A, R6
MOVC A, @A+DPTR
MOV P0, A
; P2显示个位
MOV DPTR, #TAB
MOV A, R7
MOVC A, @A+DPTR
MOV P2, A
RET
; 按键扫描
KEY_SCAN:
; 检测S1按键 (P3.2)
JNB P3.2, KEY_S1_PRESSED
; 检测S2按键 (P3.3)
JNB P3.3, KEY_S2_PRESSED
RET
KEY_S1_PRESSED:
ACALL DELAY_10MS ; 延时消抖
JB P3.2, EXIT_S1 ; 确认按键按下
; 等待按键释放
WAIT_S1_RELEASE:
ACALL DISPLAY ; 保持显示更新
JNB P3.2, WAIT_S1_RELEASE
; 计数器加1 (00-99循环)
INC R5
MOV A, R5
CJNE A, #100, UPDATE_DISPLAY
MOV R5, #0 ; 达到100则归零
UPDATE_DISPLAY:
ACALL DISPLAY ; 更新显示
EXIT_S1:
RET
KEY_S2_PRESSED:
ACALL DELAY_10MS ; 延时消抖
JB P3.3, EXIT_S2 ; 确认按键按下
; 等待按键释放
WAIT_S2_RELEASE:
ACALL DISPLAY ; 保持显示更新
JNB P3.3, WAIT_S2_RELEASE
; 发送当前计数值 (ASCII格式)
MOV A, R5
MOV B, #10
DIV AB ; A=十位, B=个位
ADD A, #30H ; 十位转ASCII
ACALL SEND_CHAR ; 发送十位
MOV A, B
ADD A, #30H ; 个位转ASCII
ACALL SEND_CHAR ; 发送个位
; 发送换行符便于查看
MOV A, #0DH ; 回车
ACALL SEND_CHAR
MOV A, #0AH ; 换行
ACALL SEND_CHAR
EXIT_S2:
RET
; 串口发送函数
SEND_CHAR:
MOV SBUF, A ; 发送字符
JNB TI, $ ; 等待发送完成
CLR TI ; 清除发送标志
RET
; 10ms延时消抖
DELAY_10MS:
MOV R0, #20
DL1:
MOV R1, #250
DL2:
DJNZ R1, DL2
DJNZ R0, DL1
RET
; 数码管段码表
; P2段码表 (用于个位显示)
TAB: DB 88H,0EBH,4CH,49H,2BH,19H,18H,0CBH,08H,09H
; P0段码表 (用于十位显示)
TABA:DB 11H,0D7H,32H,92H,0D4H,98H,18H,0D3H,10H,90H
END
尝试将串口助手接收缓存区更换为hex模式,仍有此问题,附件为hex程序
//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz
#include "reg51.h"
#include "intrins.h"
typedef unsigned char BYTE;
typedef unsigned int WORD;
#define FOSC 11059200L //系统频率
#define BAUD 115200 //串口波特率
#define NONE_PARITY 0 //无校验
#define ODD_PARITY 1 //奇校验
#define EVEN_PARITY 2 //偶校验
#define MARK_PARITY 3 //标记校验
#define SPACE_PARITY 4 //空白校验
#define PARITYBIT NONE_PARITY //定义校验位
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;
sfr AUXR= 0x8e; //辅助寄存器
sfr P_SW1 = 0xA2; //外设功能切换寄存器1
#define S1_S0 0x40 //P_SW1.6
#define S1_S1 0x80 //P_SW1.7
sbit P22 = P2^2;
bit busy;
void SendData(BYTE dat);
void SendString(char *s);
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P6M0 = 0x00;
P6M1 = 0x00;
P7M0 = 0x00;
P7M1 = 0x00;
ACC = P_SW1;
ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=0
P_SW1 = ACC; //(P3.0/RxD, P3.1/TxD)
//ACC = P_SW1;
//ACC &= ~(S1_S0 | S1_S1); //S1_S0=1 S1_S1=0
//ACC |= S1_S0; //(P3.6/RxD_2, P3.7/TxD_2)
//P_SW1 = ACC;
//
//ACC = P_SW1;
//ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=1
//ACC |= S1_S1; //(P1.6/RxD_3, P1.7/TxD_3)
//P_SW1 = ACC;
#if (PARITYBIT == NONE_PARITY)
SCON = 0x50; //8位可变波特率
#elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
SCON = 0xda; //9位可变波特率,校验位初始为1
#elif (PARITYBIT == SPACE_PARITY)
SCON = 0xd2; //9位可变波特率,校验位初始为0
#endif
AUXR = 0x40; //定时器1为1T模式
TMOD = 0x00; //定时器1为模式0(16位自动重载)
TL1 = (65536 - (FOSC/4/BAUD)); //设置波特率重装值
TH1 = (65536 - (FOSC/4/BAUD))>>8;
TR1 = 1; //定时器1开始启动
ES = 1; //使能串口中断
EA = 1;
SendString("STC15F2K60S2\r\nUart Test !\r\n");
while(1);
}
/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4
{
if (RI)
{
RI = 0; //清除RI位
P0 = SBUF; //P0显示串口数据
P22 = RB8; //P2.2显示校验位
}
if (TI)
{
TI = 0; //清除TI位
busy = 0; //清忙标志
}
}
/*----------------------------
发送串口数据
----------------------------*/
void SendData(BYTE dat)
{
while (busy); //等待前面的数据发送完成
ACC = dat; //获取校验位P (PSW.0)
if (P) //根据P来设置校验位
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 0; //设置校验位为0
#elif (PARITYBIT == EVEN_PARITY)
TB8 = 1; //设置校验位为1
#endif
}
else
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 1; //设置校验位为1
#elif (PARITYBIT == EVEN_PARITY)
TB8 = 0; //设置校验位为0
#endif
}
busy = 1;
SBUF = ACC; //写数据到UART数据寄存器
}
/*----------------------------
发送字符串
----------------------------*/
void SendString(char *s)
{
while (*s) //检测字符串结束标志
{
SendData(*s++); //发送当前字符
}
}
//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz
#define NONE_PARITY 0 //无校验
#define ODD_PARITY 1 //奇校验
#define EVEN_PARITY 2 //偶校验
#define MARK_PARITY 3 //标记校验
#define SPACE_PARITY 4 //空白校验
#define PARITYBIT NONE_PARITY //定义校验位
//-----------------------------------------
AUXR EQU 08EH //辅助寄存器
P_SW1 EQU 0A2H //外设功能切换寄存器1
S1_S0 EQU 40H //P_SW1.6
S1_S1 EQU 80H //P_SW1.7
BUSY BIT 20H.0 //忙标志位
P0M1 DATA 0x93 ; P0M1.n,P0M0.n =00--->Standard, 01--->push-pull
P0M0 DATA 0x94 ; =10--->pure input,11--->open drain
P1M1 DATA 0x91 ; P1M1.n,P1M0.n =00--->Standard, 01--->push-pull
P1M0 DATA 0x92 ; =10--->pure input,11--->open drain
P2M1 DATA 0x95 ; P2M1.n,P2M0.n =00--->Standard, 01--->push-pull
P2M0 DATA 0x96 ; =10--->pure input,11--->open drain
P3M1 DATA 0xB1 ; P3M1.n,P3M0.n =00--->Standard, 01--->push-pull
P3M0 DATA 0xB2 ; =10--->pure input,11--->open drain
P4M1 DATA 0xB3 ; P4M1.n,P4M0.n =00--->Standard, 01--->push-pull
P4M0 DATA 0xB4 ; =10--->pure input,11--->open drain
P5M1 DATA 0xC9 ; P5M1.n,P5M0.n =00--->Standard, 01--->push-pull
P5M0 DATA 0xCA ; =10--->pure input,11--->open drain
P6M1 DATA 0xCB ; P6M1.n,P6M0.n =00--->Standard, 01--->push-pull
P6M0 DATA 0xCC ; =10--->pure input,11--->open drain
P7M1 DATA 0xE1 ;
P7M0 DATA 0xE2 ;
//-----------------------------------------
ORG 0000H
LJMPMAIN
ORG 0023H
LJMPUART_ISR
//-----------------------------------------
ORG 0100H
MAIN:
CLR A
MOV P0M1, A ;设置为准双向口
MOV P0M0, A
MOV P1M1, A ;设置为准双向口
MOV P1M0, A
MOV P2M1, A ;设置为准双向口
MOV P2M0, A
MOV P3M1, A ;设置为准双向口
MOV P3M0, A
MOV P4M1, A ;设置为准双向口
MOV P4M0, A
MOV P5M1, A ;设置为准双向口
MOV P5M0, A
MOV P6M1, A ;设置为准双向口
MOV P6M0, A
MOV P7M1, A ;设置为准双向口
MOV P7M0, A
CLR BUSY
CLR EA
MOV SP,#3FH
MOV A,P_SW1
ANL A,#03FH //S1_S0=0 S1_S1=0
MOV P_SW1,A //(P3.0/RxD, P3.1/TxD)
//MOV A,P_SW1
//ANL A,#03FH //S1_S0=1 S1_S1=0
//ORL A,#S1_S0 //(P3.6/RxD_2, P3.7/TxD_2)
//MOV P_SW1,A
//
//MOV A,P_SW1
//ANL A,#03FH //S1_S0=0 S1_S1=1
//ORL A,#S1_S1 //(P1.6/RxD_3, P1.7/TxD_3)
//MOV P_SW1,A
#if (PARITYBIT == NONE_PARITY)
MOV SCON,#50H //8位可变波特率
#elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
MOV SCON,#0DAH //9位可变波特率,校验位初始为1
#elif (PARITYBIT == SPACE_PARITY)
MOV SCON,#0D2H //9位可变波特率,校验位初始为0
#endif
//-------------------------------
MOV AUXR,#40H //定时器1为1T模式
MOV TMOD,#00H //定时器1为模式0(16位自动重载)
MOV TL1,#0E8H //设置波特率重装值(65536-11059200/4/115200)
MOV TH1,#0FFH
SETBTR1 //定时器1开始运行
SETBES //使能串口中断
SETBEA
MOV DPTR,#TESTSTR //发送测试字符串
LCALL SENDSTRING
SJMP$
;-----------------------------------------
TESTSTR:
DB"STC15F2K60S2 Uart1 Test !",0DH,0AH,0
;/*----------------------------
;UART 中断服务程序
;----------------------------*/
UART_ISR:
PUSHACC
PUSHPSW
JNB RI,CHECKTI //检测RI位
CLR RI //清除RI位
MOV P0,SBUF //P0显示串口数据
MOV C,RB8
MOV P2.2,C //P2.2显示校验位
CHECKTI:
JNB TI,ISR_EXIT //检测TI位
CLR TI //清除TI位
CLR BUSY //清忙标志
ISR_EXIT:
POP PSW
POP ACC
RETI
;/*----------------------------
;发送串口数据
;----------------------------*/
SENDDATA:
JB BUSY,$ //等待前面的数据发送完成
MOV ACC,A //获取校验位P (PSW.0)
JNB P,EVEN1INACC //根据P来设置校验位
ODD1INACC:
#if (PARITYBIT == ODD_PARITY)
CLR TB8 //设置校验位为0
#elif (PARITYBIT == EVEN_PARITY)
SETBTB8 //设置校验位为1
#endif
SJMPPARITYBITOK
EVEN1INACC:
#if (PARITYBIT == ODD_PARITY)
SETBTB8 //设置校验位为1
#elif (PARITYBIT == EVEN_PARITY)
CLR TB8 //设置校验位为0
#endif
PARITYBITOK: //校验位设置完成
SETBBUSY
MOV SBUF,A //写数据到UART数据寄存器
RET
;/*----------------------------
;发送字符串
//----------------------------*/
SENDSTRING:
CLR A
MOVCA,@A+DPTR //读取字符
JZ STRINGEND //检测字符串结束标志
INC DPTR //字符串地址+1
LCALL SENDDATA //发送当前字符
SJMPSENDSTRING
STRINGEND:
RET
//-----------------------------------------
END
void Uart1_Isr(void) interrupt 4
{
if (TI) //检测串口1发送中断
{
TI = 0; //清除串口1发送中断请求位
}
if (RI) //检测串口1接收中断
{
RI = 0; //清除串口1接收中断请求位
}
}
void Uart1_Init(void) //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE0; //设置定时初始值
TH1 = 0xFE; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
ES = 1; //使能串口1中断
}
ORG 0023H
UART1_ISR:
JNB TI,CHKUART1RI ;检测串口1发送中断
CLR TI ;清除串口1发送中断请求位
CHKUART1RI:
JNB RI,UART1ISREXIT ;检测串口1接收中断
CLR RI ;清除串口1接收中断请求位
UART1ISREXIT:
RETI
UART1_INIT: ;9600bps@11.0592MHz
MOV SCON,#50H ;8位数据,可变波特率
ORL AUXR,#40H ;定时器时钟1T模式
ANL AUXR,#0FEH ;串口1选择定时器1为波特率发生器
ANL TMOD,#0FH ;设置定时器模式
MOV TL1,#0E0H ;设置定时初始值
MOV TH1,#0FEH ;设置定时初始值
CLR ET1 ;禁止定时器中断
SETB TR1 ;定时器1开始计时
SETB ES ;使能串口1中断
RET
https://www.stcaimcu.com/data/download/Datasheet/STC15-CN.pdf
最新 数据手册
神农鼎 发表于 2025-6-22 17:45
感谢大佬{:baoquan:}
页:
[1]