## 485串口
## STC的坑
STC单片机发送数据给485串口的时候,发数据一样平常都没有问题,但是收数据的时候,一样平常收不到。我改动了两版电路板,才得到精确的办法。STC新版的单片机和以前的不一样了。部分不具备直接驱动485串口的能力了。

本次例程采取的单片机为STC15W408AS
不多说,直接上程序和事理图。
这是我的一个项目程序,这里只给出部分代码,须要完成代码的点击下面:
链接:https://pan.baidu.com/s/1JsI3CQcK9qkFAscv32SHqA
提取码:7a2y
程序:
main.c
/本地常量声明/
#define MAIN_Fosc11059200L//定义主时钟
#defineBaudRate19600UL//选择波特率
#defineTimer1_Reload(65536UL -(MAIN_Fosc / 4 / BaudRate1))//Timer 1 重装值, 对应300KHZ
#defineTimer2_Reload(65536UL -(MAIN_Fosc / 4 / BaudRate1))//Timer 2 重装值, 对应300KHZ
#include"STC15Fxxxx.H"
#include "i2c.h"
#include"intrins.h"
#include "stdio.h"
#define BELL P14
#define Control P55
#define Change P33
/本地变量声明/
int timeCount=0;
u8 UsartRX[20]={0,0,0,0,0,0,0,0,0,0};
u8 UsartTX[20]={0,0,0,0,0,0,0,0,0,0};
u16 UsartTime=0;
u8 UsartLength=0;
u8 UsartFlag=0;
/本地函数声明/
void init_Time0();
void delay_10US(u32 US);
char putchar(char ch);
u16Get_ADC10bitResult(u8 channel);
//
void main(void)
{
u8 i=0,flag=0;
u16 AD=0,data1=0,data2=0;
u32 address=0;
init_Time0();
P3M1=0X60;
P3M0=0X9F;
P5M1=0x00;
P5M0=0xFF;
S1_8bit();//8位数据
S1_USE_P36P37();//UART1 利用P30 P31口默认
AUXR &= ~(1<<4);//Timer stop波特率利用Timer2产生
AUXR |= 0x01;//S1 BRT Use Timer2;
AUXR |= (1<<2);//Timer2 set as 1T mode
TH2 = (u8)(Timer2_Reload >> 8);
TL2 = (u8)Timer2_Reload;
AUXR |= (1<<4);//Timer run enable
REN = 1;//许可吸收
ES = 1;//许可中断
EA = 1;//许可全局中断
//
//数据初始化
// 蜂鸣器
BELL=0;
//继电器
Control=0;
//启动看门狗
WDT_CONTR=0x3f;
P54=0;
while (1)
{
//复位单片机
if(timeCount%100)
{
WDT_CONTR&=0x7f;
WDT_CONTR|=0x10;
}
else if(timeCount>1000)
{
timeCount=0;
AD=Get_ADC10bitResult(2);
//printf("电压:%d\n",AD);
}
//判断是否吸收到数据
if((UsartTime>10)&&(UsartFlag==1))
{
UsartFlag=0;
P54=1;
delay_10US(60);
for(i=0;i<UsartLength;i++)
{
TI=0;
if(!TI)
{
SBUF=UsartRX[i];
}
TI=1;
delay_10US(5);
}
P54=0;
UsartLength=0;
}
}
}
/ UART1中断函数/
/ UART1中断函数/
void UART1_int (void) interrupt UART1_VECTOR
{
TR0=0;
if(RI)
{
RI=0;
//判断收到的数据是否为第一位
if(UsartTime>=10)
{
UsartTime=0;
UsartRX[0]=SBUF;
UsartLength=1;
UsartFlag=1;
}
else
{
UsartTime=0;
UsartRX[UsartLength]=SBUF;
UsartLength++;
UsartFlag=1;
}
}
TR0=1;
}
/
功 能:定时器0初始化函数
返回值:无
参 数:无
/
void init_Time0()
{
TMOD|=0X01;//定时器的事情模式为1,计数的位数为16位
TH0=0XFC;
TL0=0X65; //计数的个数为922,定时为1US
EA=1;//打开总中断
ET0=1;//定时器T0许可中断
TR0=1;//定时器T0开始事情
}
/
功 能:定时器0中断函数
返回值:无
参 数:无
/
void interrupt_time0(void) interrupt 1
{
TH0=0XFC;
TL0=0X65; //计数的个数为922,定时为1US
timeCount++;
UsartTime++;
if(UsartTime>100)
{
UsartTime=11;
}
}
void delay_10US(u32 US)
{
unsigned int i;
do{
i = MAIN_Fosc / 1300000;
while(--i); //14T per loop
}while(--US);
}
char putchar(char ch)
{
SBUF = ch;
while(TI == 0);
TI = 0;
return ch;
}
/
功 能:得到电压值
返回值:所在通道的电压值
参 数:channel为所在的通道
/
u16Get_ADC10bitResult(u8 channel)//channel = 0~7
{
//AD引脚定义配置
P1ASF= 0x03;//P1.2 P1.3做ADC
ADC_CONTR = 0xE0;//90T, ADC power on
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = (ADC_CONTR & 0xe0) | 0x08 | channel; //start the ADC
NOP(4);
while((ADC_CONTR & 0x10) == 0);//wait for ADC finish
ADC_CONTR &= ~0x10;//打消ADC结束标志
P1ASF= 0x00;//P1.2 P1.3做ADC
ADC_CONTR = 0x00;//90T, ADC power on
//P1M1=0X02; //配置SDA为输入
// P1M0=0X00;
return(((u16)ADC_RES << 2) | (ADC_RESL & 3));
}
事理图部分,下图电阻R18 R15 R21不焊接。