帮网友答疑解惑ing
帮忙 答疑解惑型号 STC15F2K32S2 串口调试 如果主程序空跑,串口他就会发回八个数据;(主程序里循环里基本上没有东西,只用串口)上电后不正常,发4个收到8个,要按一下按键才正常,
目前网友解决办法是: 在主程序中加了一个40MS的延时就正常了。
另外,想了解一下: 串口是中断,和扫描周期有什么关系?
估计初学者,你给他 STC15实验箱的演示程序
楼主遇到的问题,是程序的问题。请直接测试官方例程。
现在的问题,不是不能收发, 为何加延时就正常了,原因是什么?我们要找到问题点,并非一律去用通用程序去测试,下次复杂一点就不会了。。。。:'(:'(:'( 方法:从正确的程序出发,而不是从错误的程序出发 !
有人愿意学习别人错误的程序吗,我们的风格是给正确的程序给大家去修改
这有复杂的正确的程序参考
【新提醒】求STC8H/STC8G系列 4个串口同时通信的演示程序,Modbus 演示程序 - 串行口,DMA支持的4组串口 国芯论坛 (stcaimcu.com)
#include<STC15F2K60S2.h>
#include<INTRINS.h>
#include <string.h>
//#include<stdio.h>
#defineuint unsigned int
#defineuchar unsigned char
#define FOSC 11059200L
#define T1MS (65536-FOSC/1000) //1T模式
sbit Y1=P0^0;
sbit Y2=P0^1;
sbit Y3=P0^2;
sbit Y4=P0^3;
sbit Y5=P0^4;
sbit Y6=P0^5;
sbit Y7=P0^6;
sbit Y8=P0^7;
sbit Y9=P1^2;
sbit Y10=P1^3;
sbit Y11=P1^4;
sbit Y12=P1^5;
sbit Y13=P2^0;
sbit Y14=P2^1;
sbit Y15=P2^2;
sbit Y16=P2^3;
sbit Y17=P2^4;
sbit Y18=P2^5;
sbit Y19=P2^6;
sbit Y20=P2^7;
sbit Y21=P3^2;
sbit Y22=P3^3;
sbit Y23=P3^4;
sbit Y24=P3^5;
sbit Y25=P3^6;
sbit Y26=P3^7;
sbit Y27=P4^0;
sbit Y28=P4^1;
sbit Y29=P4^2;
sbit Y30=P4^3;
sbit Y31=P4^4;
sbit Y32=P4^5;
sbit Y33=P4^6;
sbit Y34=P4^7;
sbit X1 =P5^5;
ucharStr=0;//定义一维空数组用于存放串口收到的数据
uchar key_s1 ,S1,S2;
uchar moshi1,moshi2,tongguo;
uint yanshi,yanshi1=5000;
uchar SDJS;
uchar M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,
M11,M12,M13,M14,M15,M16,M17,M18,M19,M20,
M21,M22,M23,M24,M25,M26,M27,M28,M29,M30,
M31,M32,M33,M34,M100; //中间继电器
void InitRS232() //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0xE0; //设定定时初值
T2H = 0xFE; //设定定时初值
AUXR |= 0x10; //启动定时器2
REN = 1; //允许接收
ES= 1; //允许中断
EA = 1; //允许全局中断
}
void SendData(unsigned char c)
{
ES=0;
SBUF=c;
while(!TI);
TI=0;
ES=1;
}
void SendString( unsigned char *Data)//串口发送字符
{
while(*Data)
{
SendData(*Data++);
}
}
void Delayms(uint k) //@11.0592MHz1ms
{
uint i, j;
for(i=k;i>0;i--)
for(j=120;j>0;j--);
}
void main() ///////////////////////////////////
//产品感应 X0 启动X1进出气缸原点X2 进出气缸到位 X3 铁片气缸原点 X4 铁片气缸到位 X5
//进出气缸Y0 铁片气缸Y1PASS Y2FAIL Y3蜂鸣器Y4
{
InitRS232();
M1=0;M2=0;M3=0;M4=0; M5=0;M6=0;M7=0;M8=0; M9=0;M10=0;
M11=0;M12=0;M13=0;M14=0; M15=0;M16=0;M17=0;M18=0; M19=0;M20=0;
M21=0;M22=0;M23=0;M24=0; M25=0;M26=0;M27=0;M28=0; M29=0;M30=0;
M31=0;M32=0;M33=0;M34=0;M100=0;
SDJS=0;
// Str=0x00; Str=0x00; Str=0x00; Str=0x00;
while(1)
{
///////////////////////////测试模式/////////////////////////////
Y34=0;
Delayms(20);
Y34=1;
Delayms(20); /////这四句不加,串口不正常,会返回8个字节,猜测是程序不能空跑?
if(X1==0&&key_s1==0)
{
Delayms(20);
if(X1==0) //启动按钮按下
{key_s1=1;
SDJS++;
M100=1;//手动标志位
//if(SDJS==34)SDJS=1;
while(X1==0);
key_s1=0;
}
// if(SDJS==1) Y1=0;
// if(SDJS==2) Y2=0;
// if(SDJS==3) Y3=0;
if(M100)
{
switch (SDJS)
{
case 1: Y32=1; Y1=0; break ;
case 2: Y1=1; Y2=0;break ;
case 3: Y2=1; Y3=0; break ;
case 4: Y3=1; Y4=0; break ;
case 5: Y4=1; Y5=0; break ;
case 6: Y5=1;Y6=0; break ;
case 7: Y6=1; Y7=0; break ;
case 8: Y7=1; Y8=0; break ;
case 9: Y8=1;Y9=0; break ;
case 10: Y9=1; Y10=0;break ;
case 11: Y10=1; Y11=0; break ;
case 12: Y11=1; Y12=0; break ;
case 13: Y12=1; Y13=0; break ;
case 14: Y13=1; Y14=0; break ;
case 15: Y14=1; Y15=0; break ;
case 16: Y15=1; Y16=0; break ;
case 17: Y16=1; Y17=0; break ;
case 18: Y17=1; Y18=0; break ;
case 19: Y18=1; Y19=0;break ;
case 20: Y19=1; Y20=0; break ;
case 21: Y20=1; Y21=0; break ;
case 22: Y21=1; Y22=0; break ;
case 23: Y22=1; Y23=0; break ;
case 24: Y23=1; Y24=0; break ;
case 25: Y24=1; Y25=0; break ;
case 26: Y25=1; Y26=0; break ;
case 27: Y26=1; Y27=0;break ;
case 28: Y27=1; Y28=0; break ;
case 29: Y28=1; Y29=0; break ;
case 30: Y29=1; Y30=0; break ;
case 31: Y30=1; Y31=0; break ;
case 32: Y31=1; Y32=0; break ;
case 33: Y32=1; SDJS=0;M100=0; break ;
default : break ;
}
}
}
}
}
/******************************************************************/
/* 串口中断 */
/******************************************************************/
void UART_SER (void) interrupt 4 //M1=1出窗M2=1铁片远离M3=1铁皮靠近
{
unsigned char Temp,Num,EnterTag; //临时变量
if(TI) //如果是发送标志则清0
TI=0;//
if(RI) //接收中断?
{
RI=0; //标志清0
Temp=SBUF; //存入临时变量
if(Temp==0X02||tongguo==1)
{
tongguo=1;//通过标志,接收到数据开始位则打开通过标志,直到接收到结束标志才清零
Str=Temp;//存入一维数组中
Num++;
if(Num==4)
{
tongguo=0;
EnterTag=1;
Num=0;
}
if(EnterTag)
{
if(Str==0xFE&&Str==0xFF)//全OFF
{
Y1=1;Y2=1; Y3=1;Y4=1; Y5=1;Y6=1; Y7=1;Y8=1; Y9=1;Y10=1;
Y11=1;Y12=1; Y13=1;Y14=1; Y15=1;Y16=1; Y17=1;Y18=1; Y19=1;Y20=1;
Y21=1;Y22=1; Y23=1;Y24=1; Y25=1;Y26=1; Y27=1;Y28=1; Y29=1;Y30=1;
Y31=1;Y32=1; Y33=1;Y34=1; SDJS=0;
EnterTag=0;
}
if(Str==0xFF&&Str==0xFF) //全ON
{
Y1=0;Y2=0; Y3=0;Y4=0; Y5=0;Y6=0; Y7=0;Y8=0; Y9=0;Y10=0;
Y11=0;Y12=0; Y13=0;Y14=0; Y15=0;Y16=0; Y17=0;Y18=0; Y19=0;Y20=0;
Y21=0;Y22=0; Y23=0;Y24=0; Y25=0;Y26=0; Y27=0;Y28=0; Y29=0;Y30=0;
Y31=0;Y32=0; Y33=0;Y34=0;
EnterTag=0;
}
if(Str==0x01&&Str==0xFF)
{
if( Str==0x01) Y1=0;
if( Str==0x00) Y1=1;
EnterTag=0;
}
if(Str==0x02&&Str==0xFF)
{
if( Str==0x01) Y2=0;
if( Str==0x00) Y2=1;
EnterTag=0;
}
if(Str==0x03&&Str==0xFF)
{
if( Str==0x01) Y3=0;
if( Str==0x00) Y3=1;
EnterTag=0;
}
if(Str==0x04&&Str==0xFF)
{
if( Str==0x01) Y4=0;
if( Str==0x00) Y4=1;
EnterTag=0;
}
if(Str==0x05&&Str==0xFF)
{
if( Str==0x01) Y5=0;
if( Str==0x00) Y5=1;
EnterTag=0;
}
if(Str==0x06&&Str==0xFF)
{
if( Str==0x01) Y6=0;
if( Str==0x00) Y6=1;
EnterTag=0;
}
if(Str==0x07&&Str==0xFF)
{
if( Str==0x01) Y7=0;
if( Str==0x00) Y7=1;
EnterTag=0;
}
if(Str==0x08&&Str==0xFF)
{
if( Str==0x01) Y8=0;
if( Str==0x00) Y8=1;
EnterTag=0;
}
if(Str==0x09&&Str==0xFF)
{
if( Str==0x01) Y9=0;
if( Str==0x00) Y9=1;
EnterTag=0;
}
if(Str==0x0A&&Str==0xFF)
{
if( Str==0x01) Y10=0;
if( Str==0x00) Y10=1;
EnterTag=0;
}
if(Str==0x0B&&Str==0xFF)
{
if( Str==0x01) Y11=0;
if( Str==0x00) Y11=1;
EnterTag=0;
}
if(Str==0x0C&&Str==0xFF)
{
if( Str==0x01) Y12=0;
if( Str==0x00) Y12=1;
EnterTag=0;
}
if(Str==0x0D&&Str==0xFF)
{
if( Str==0x01) Y13=0;
if( Str==0x00) Y13=1;
EnterTag=0;
}
if(Str==0x0E&&Str==0xFF)
{
if( Str==0x01) Y14=0;
if( Str==0x00) Y14=1;
EnterTag=0;
}
if(Str==0x0F&&Str==0xFF)
{
if( Str==0x01) Y15=0;
if( Str==0x00) Y15=1;
EnterTag=0;
}
if(Str==0x10&&Str==0xFF)
{
if( Str==0x01) Y16=0;
if( Str==0x00) Y16=1;
EnterTag=0;
}
if(Str==0x11&&Str==0xFF)
{
if( Str==0x01) Y17=0;
if( Str==0x00) Y17=1;
EnterTag=0;
}
if(Str==0x12&&Str==0xFF)
{
if( Str==0x01) Y18=0;
if( Str==0x00) Y18=1;
EnterTag=0;
}
if(Str==0x13&&Str==0xFF)
{
if( Str==0x01) Y19=0;
if( Str==0x00) Y19=1;
EnterTag=0;
}
if(Str==0x14&&Str==0xFF)
{
if( Str==0x01) Y20=0;
if( Str==0x00) Y20=1;
EnterTag=0;
}
if(Str==0x15&&Str==0xFF)
{
if( Str==0x01) Y21=0;
if( Str==0x00) Y21=1;
EnterTag=0;
}
if(Str==0x16&&Str==0xFF)
{
if( Str==0x01) Y22=0;
if( Str==0x00) Y22=1;
EnterTag=0;
}
if(Str==0x17&&Str==0xFF)
{
if( Str==0x01) Y23=0;
if( Str==0x00) Y23=1;
EnterTag=0;
}
if(Str==0x18&&Str==0xFF)
{
if( Str==0x01) Y24=0;
if( Str==0x00) Y24=1;
EnterTag=0;
}
if(Str==0x19&&Str==0xFF)
{
if( Str==0x01) Y25=0;
if( Str==0x00) Y25=1;
EnterTag=0;
}
if(Str==0x1A&&Str==0xFF)
{
if( Str==0x01) Y26=0;
if( Str==0x00) Y26=1;
EnterTag=0;
}
if(Str==0x1B&&Str==0xFF)
{
if( Str==0x01) Y27=0;
if( Str==0x00) Y27=1;
EnterTag=0;
}
if(Str==0x1C&&Str==0xFF)
{
if( Str==0x01) Y28=0;
if( Str==0x00) Y28=1;
EnterTag=0;
}
if(Str==0x1D&&Str==0xFF)
{
if( Str==0x01) Y29=0;
if( Str==0x00) Y29=1;
EnterTag=0;
}
if(Str==0x1E&&Str==0xFF)
{
if( Str==0x01) Y30=0;
if( Str==0x00) Y30=1;
EnterTag=0;
}
if(Str==0x1F&&Str==0xFF)
{
if( Str==0x01) Y31=0;
if( Str==0x00) Y31=1;
EnterTag=0;
}
if(Str==0x20&&Str==0xFF)
{
if( Str==0x01) Y32=0;
if( Str==0x00) Y32=1;
EnterTag=0;
}
if(Str==0x21&&Str==0xFF)
{
if( Str==0x01) Y33=0;
if( Str==0x00) Y33=1;
EnterTag=0;
}
if(Str==0x22&&Str==0xFF)
{
if( Str==0x01) Y34=0;
if( Str==0x00) Y34=1;
EnterTag=0;
}
SendData(Str);
SendData(Str);
SendData(Str);
SendData(Str);
}
}
}
}
这是全部程序,麻烦帮忙找一下关于串口的错误,谢谢! lzne5532 发表于 2023-2-1 17:41
现在的问题,不是不能收发, 为何加延时就正常了,原因是什么?我们要找到问题点,并非一律去用通用程序去 ...
估计问题出在sbuf缓冲器上, 51只有单个 sbuf, 上位机数据发送速率快, 查询方式往往速度跟不上, 来不及从串口中读数据而丢失数据.
主动发送数据, 上位机回送, 也存在这种现像.
我以前在 51(12T)上, 通讯速率 9600, 就碰到这种情况, 用中断方式, 中断响应慢一点, 还是要间断性的丢失数据.解决不了 Numh换成全局变量或者加static修饰符,局部变量每次进中断都会临时分配ram,不是你期望的值,正常的时候只是凑巧编译器在进中断的时候给Num分配了同一个地址的内存。还有就是这种接收方式不靠谱,还敢用在工业环境:以字节数作为分包解析的基础,假如线上面受到干扰,或者说上电时串口收到一个值,你数组里面的值全部会错位。可以用超时分包机制或者用帧头帧尾分包 LAOXU 发表于 2023-2-3 06:14
估计问题出在sbuf缓冲器上, 51只有单个 sbuf, 上位机数据发送速率快, 查询方式往往速度跟不上, 来不及从 ...
串口都要用中断方式收发,特别是接收。比如115200的波特率,86.8us中断一次,进中断读SBUF保存在接收数组耗时一般不超过2us,4个串口同时115200收发都不会有问题。其他中断不要耗太多时间,如果耗时多,则将串口中断设置为高优先级,其余中断为低优先级。
还可以使用带DMA的MCU来处理串口接收,比如STC32G12K128系列、STC8H8K64U系列、STC8H4K64TL系列、STC8H8K64TLCD系列、STC8A8K64D4系列等等
页:
[1]
2