本帖最后由 北航吴彦祖 于 2017-12-28 22:19 编辑
求问。
PIC18F2423单片机,使用RS485通信,编译环境MPLAB IDEV8.91。
在通信时,串口接收信号正确,将接收的数据帧从RCREG寄存器中读取出来,赋值给别的变量,数据就产生了变化,变化很固定,请问这是什么原因?已查明不是电路的问题。第一次发帖,求大神回复!
#include<pic18.h> //包含单片机内部资源预定义
#include<pic18f4523.h>
#include <stdio.h>
#include "main.h"
#include "sci.h"
//函数区========================================================================
void main()
{
GIE=0; //禁止中断
io_init(); //初始化
timer_init();
sci_init();
sys_init(); //处理中断等
adc_init();
GIE=1; //开中断
PEIE=1;
while(1)
{
if (**1ms)
{
**1ms=0;
}
if (**_ADtime)
{
AD_go(); //启动一次AD转换
**_ADtime=0;
}
if(tx**)
{
tx**=0;
Sci2Tx();
}
ms_delay(2);
} //等待接收中断
}
/*========================================================================
========================================================================*/
void io_init(void)
{
PORTA=0b00101111; //RA0、RA1、RA2、RA3、RA5输入
TRISA=0b00101111;
PORTB=0b00001110; //RB1、RB2、RB3输入
TRISB=0b00001110;
TRISC=0b00000000;
// PORTC&=0b11101111;
}
//=========SCI串口函数==========================================================
void sci_init(void)
{
SPBRG=103; //16MHz-9600
//波特率计算公式
//1.同步方式:波特率=Fosc/[4(X+1)]
//2.异步方式:BRGH=0:波特率=Fosc/[64(x+1)]
// BRGH=1:波特率=Fosc/[16(x+1)]
BAUDCON&=~(1<<3); //BRG16=0
TRISC|=(1<<7); //RC7置1设置为输入
TRISC&=~(1<<6); //RC6置0设置为输出
EnRS485Receive2();
TXSTA=0x24;//异步,高速(BRGH=1),8位
RCSTA=0x90; //使能UART
RCIF=0;
TXIF=0; //清除UART2中断标志
IPR1|=(1<<4)|(1<<5); //usart1高优先级
RCIE=1; //使能收中断
TXIE=0; //禁止发送中断
orderRxSci1=0;
tx**=0;
}
//=========AD函数==========================================================
void adc_init(void)
{
ADCON1=0x00; //参考电压VDD VSS;
ADCON0=0x01; //选择通道0(bit6:2),使能ADC
ADCON2=0xB5; //右对齐,16Tad,Foc/16(Tad=1us)
ADIF=0; //清除AD转换标志
ADIE=1; //AD中断允许
}
//AD改变通道channel:0~7
void AD_ch_change(void)
{
const uchar AD_ch_set[]={
0b00000001,0b00000101,0b00001001,0b00001101,0b00010001,0b00100001,0b00100101,0b00101001};
ADchannel++;
ADchannel%=8;
ADCON0=AD_ch_set[ADchannel];
}
void AD_deal(void)
{
if(AD_data[ADchannel]<5) //AD采样处理,防止溢出
{
AD_data[ADchannel]=0;
}
if(AD_data[ADchannel]>4095)
{
AD_data[ADchannel]=4095;
}
if(ADchannel<=7) //八个通道数据存在AD[]里
{
AD[ADchannel]=((AD_vol*AD_data[ADchannel]))/AD_acc;
}
}
//=========系统==========================================================
void sys_init(void)
{
SWDTEN=0; //关看门狗
IPEN=1; //中断优先级,置1使能
INTCON=0xF0; //允许高低中断、TIM0中断、INT0中断
INTCON2=0x00; //下降沿触发
INTCON3=0xC8; //允许INT1中断,外部中断高优先级
PIE1=0x60; //允许中断:AD,RC
PIR1=0;
}
//=========定时器函数==========================================================
void timer_init(void)
{
T0CON=0x45; //8位定时器,16M晶振64分频,需要计数250次
TMR0IF=0; //标志位清0
TMR0IE=1; //允许溢出中断
TMR0IP=0; //TIM0中断 低优先级
TMR0=0x05; //定时常数5 =1ms
TMR0ON=1; //使能TIM0
}
//***********************************
void us_delay(uchar us) //延时函数
{
uchar i, j;
for(i=0;i<16;i++)
{
for(j=0;j<us;j++)
{;}
}
}
void ms_delay(uchar ms) //延时函数
{
uint i;
uchar j;
for(i=0;i<16000;i++)
{
for(j=0;j<ms;j++)
{;}
}
}
void interrupt HI_ISR()
{
if(INT0IF) //INT0外部中断
{
INT0IF=0;
//**添加代码
}
if(INT1IF) //INT1外部中断
{
INT1IF=0;
//**添加代码
}
if(RCIF) //如果是串口接收中断的话,则进入中断处理
{
RCIF=0;
Sci2Rx();
}
}
//***********************************
void interrupt low_priority LOW_ISR()
{
if(ADIF) //判断是否是AD转换中断
{
ADIF=0; //清0
AD_data[ADchannel]=(ADRESH<<8|ADRESL);
AD_deal();
AD_ch_change();
}
if(TMR0IE)
{ //确认是定时器0中断
if(TMR0IF)
{
**1ms=1;
ms_temp++;
TMR0IF=0;
TMR0=0x05; //1ms定时常数
if(ms_temp==AD_time) //定时到
{
**_ADtime=1;
ms_temp=1;
}
}
}
}
/*从单片机发单个字节到单片机)*/
void UART_sendchar(uchar dad)
{
EnRS485Trans2();
TXREG=dad;
while(0==TXSTAbits.TRMT);
EnRS485Receive2();
}
void Sci2Tx(void) //发送函数
{
uchar i;
i=0;
qishizifu=0xED;
txBuf[0]=0xEE; //本机地址
txBuf[1]=0x03; //功能码
txBuf[2]=0x0F; //字节数
for(ADchannel=0;ADchannel<1;ADchannel++)
{
txBuf[(ADchannel+1)*2+1]=(uchar)AD_data[ADchannel]; //低八位传输赋值
txBuf[(ADchannel+1)*2+2]=(uchar)(AD_data[ADchannel]>>8); //高低八位传输赋值
}
crc[0]=GenertCrc(txBuf,19)>>8; //crc码传输
crc[1]=GenertCrc(txBuf,19);
endzifu=0xEF;
UART_sendchar(qishizifu);
UART_sendchar(txBuf[0]);
UART_sendchar(txBuf[1]);
UART_sendchar(txBuf[2]);
UART_sendchar(txBuf[3]);
UART_sendchar(txBuf[4]);
UART_sendchar(crc[0]);
UART_sendchar(crc[1]);
UART_sendchar(endzifu);
}
INT16U GenertCrc(INT8U *str, INT16U num) //crc码生成函数
{
INT16U crc=0xFFFF;
INT16U genertCrc_i=0,genertCrc_j=0;
INT8U **Crc;
for (genertCrc_i=0;genertCrc_i<num;genertCrc_i++)
{
crc=str[genertCrc_i]^crc;
for (genertCrc_j=0;genertCrc_j<8;genertCrc_j++)
{
**Crc=crc&0x0001;
crc>>=1;
if (**Crc)
{
crc^=0xA001;
}
}
}
genertCrc_i=crc;
crc<<=8; //调整结果的高8位和低8位
crc|=(genertCrc_i>>8);
return(crc);
}
==========================================================================================*/
void Sci2Rx(void) //RS485接收请求
{
dataRxSci1=RCREG;
if((0==orderRxSci1)&&(0xED==dataRxSci1Pre))
{
rxBufSci1[0]=0xED;
orderRxSci1=1; //帧头正确则进入下一状态
}
dataRxSci1Pre=dataRxSci1;
if(orderRxSci1>0)
{
rxBufSci1[orderRxSci1]=dataRxSci1; //将接收到的字节赋给数组
orderRxSci1++;
}
if(orderRxSci1==10) //判断是否是单片机3发来的请求
{
tx**=1;
}
if(orderRxSci1==10)
{
orderRxSci1=0;
dataRxSci1Pre=0xFF;
}
}
|