PIC18F87K90程序,注意串口2要关闭端口模拟功能后才能使用(ANCON2我在这里吃过亏),以下是调试好的程序。
//单片机引脚定义******************************************************************************
LCDSE0=0;LCDSE1=0;LCDSE2=0;LCDSE3=0;LCDSE4=0;LCDSE5=0;LCDEN=0;//关闭液晶驱动功能
OSCCON=0x46;//使用内部16M晶振8分频=2M
PORTA=0;LATA=0;TRISA=0;
PORTB=0;LATB=0;TRISB=0x0B;RBPU=0;//按键引脚和OK指示灯定义
PORTC=0;LATC=0;TRISC=0xC0;//SPI1,串口1,工作指示灯引脚定义
PORTD=0;LATD=0;TRISD=0x20;RDPU=1;//数码管显示,RS485控制,看门狗引脚定义
PORTE=0;LATE=0;TRISE=0;//LED引脚定义
PORTF=0;LATF=0;TRISF=0;
PORTG=0;LATG=0;TRISG=0x04;//串口2引脚定义
PORTH=0;LATH=0;TRISH=0;
ODCON1=0;ODCON2=0;ODCON3=0;
ANCON2=0;//我原来认为默认值应该是0,实际是0xFF,再次提醒。
//以下是中断定义******************************************************************************
GIE=0;//中断: 1允许所有高优先级中断 0禁止所有中断
PEIE=0;//中断: 1允许所有低优先级中断 0禁止所有中断
//初始化前,应禁止中断,以下中断初始化
PIR1=0;//中断标志清零
IPEN=1;//中断优先级设置:1允许优先级 0禁止优先级
TMR0IP=1;//TMR0 溢出中断优先级位: 1高优先级 0低优先级
IPR1=0x20;//串口1 优先级
IPR2=0;
IPR3=0x00;//串口2 优先级
IPR4=0;IPR5=0;IPR6=0;//其它低优先级
TMR0IE=1;//TMR0 溢出中断允许位: 1允许 0禁止
PIE1=0x20;//允许串口1中断,允许AD中断
PIE2=0;
PIE3=0x20;//允许串口2中断
PIE4=0;PIE5=0;PIE6=0;
/******************************************************************************/
/*初始化函数 串口1*/
/******************************************************************************/
void Usart_init1(void)
{
ABDEN=0;//关闭自动波特率检测
BRG16=1;//选择波特率生成器为16方式
BRGH=1;//选择高速波特率方式
SYNC=0;//选择异步方式
SPBRGH1=0;
SPBRG=0x33;//设置波特率为9600BPS,9600=2M/4(0x33+1)
SPEN=1;//使能串口发送,选择高速波特率
TXEN=1;
RCSTA1=0x90;//使能串口工作,连续接收
}
/******************************************************************************/
/*初始化函数 串口2*/
/******************************************************************************/
void Usart_init2(void)
{
ABDEN2=0;//关闭自动波特率检测
BRG162=1;//选择波特率生成器为16方式
BRGH2=1;//选择高速波特率方式
SYNC2=0;//选择异步方式
SPBRG2H=0;
SPBRG2=0x33;//设置波特率为9600BPS,9600=2M/4(0x33+1)
SPEN2=1;//使能串口发送,选择高速波特率
TXEN2=1;
RCSTA2=0x90;//使能串口工作,连续接收
}
/*****************************************************************************/
/*ASCII转成十六进制*/
/*****************************************************************************/
unsigned char ASCII(unsigned char dataf)
{
unsigned char resc;
if(dataf<=0x39) resc=dataf-0x30;
else resc=dataf-0x37;
return resc;
}
/******************************************************************************/
/*发送函数 串口1*/
/******************************************************************************/
void Usart_T(unsigned char dataf)
{
int index;
RS485=1;
for(index=0;index<1000;index++)//检测发送器是否为空
{
if(TRMT==1)break;
}
TXREG1=dataf;//把数据写入缓冲区
for(index=0;index<1000;index++)//等待发送完毕
{
if(TX1IF==1)break;
}
RS485=0;
//TX1IF=0;//发送中断清零
}
/****************************************************************************/
/*发送函数 num个 数据 串口1*/
/****************************************************************************/
void Usart_Tm(unsigned char *data,unsigned char num)
{
unsigned char i;
for(i=num;i>0;i--)
{
Usart_T(*data);
data++;
}
}
/******************************************************************************/
/*发送函数 串口2*/
/******************************************************************************/
void Usart_T2(unsigned char dataf)
{
int index;
//RS485=1;
for(index=0;index<1000;index++)//检测发送器是否为空
{
if(TRMT2==1)break;
}
TXREG2=dataf;//把数据写入缓冲区
for(index=0;index<1000;index++)//等待发送完毕
{
if(TX2IF==1)break;
}
//RS485=0;
//TX2IF=0;//发送中断清零
}
/****************************************************************************/
/*发送函数 num个 数据 串口2*/
/****************************************************************************/
void Usart_Tm2(unsigned char *data,unsigned char num)
{
unsigned char i;
for(i=num;i>0;i--)
{
Usart_T2(*data);
data++;
}
}
/******************************************************************************/
/*串口中断函数 1*/
/******************************************************************************/
void interrupt Usart(void)
{
unsigned char index_comm,buf_comm;
unsigned char rx_buf;
if(TMR0IF==1)//定时器0中断处理
{
TMR0IF=0;
TMR0L=0;
TMR0H=0xF0;
set_time++;
if(set_time>=500)set_time_over=1;
}//end if(TMR0IF==1)
if(RC1IF==1)//串口1中断处理
{
rx_buf=RCREG1;
if(rx_buf == 0x3A)//界定符
{
com_data_num =0;
start_receive_data_flag = 1;
}
if(start_receive_data_flag==1)//开始接收界定符、地址、数据及结束符。
{
ser_buf[com_data_num] = rx_buf;
com_data_num++;
if(rx_buf == 0x0A)//0x0d 回车 为结束符
{
start_receive_data_flag = 0;
ser_process_data_flag = 1;
}
}
if(ser_process_data_flag==1)
{
rx_buf=(ser_buf[5]-0x30)*10+ ser_buf[6]-0x30+6;//提取数据长度
buf_comm=0;
for(index_comm=1;index_comm<=rx_buf;index_comm++)//计算校验和
buf_comm=buf_comm+ser_buf[index_comm];
//if(buf_comm==((ASCII(ser_buf[rx_buf+1]))*16+ASCII(ser_buf[rx_buf+2])))//比较校验和
{
//ser_com();//串口命令处理程序
Usart_Tm(ser_buf,com_data_num);
}
ser_process_data_flag = 0;
}
}//end if(RC1IF==1)
}
/******************************************************************************/
/*串口中断函数 2*/
/******************************************************************************/
void interrupt low_priority Usart2(void)
{
unsigned char index_comm,buf_comm;
unsigned char rx_buf;
/*
if(ADIF==1)
{
ADIF=0;
adc[adc_start][ad_index]=ADRESH*256+ADRESL;
ad_index++;
if(ad_index>=AD_BUF_NUM)
{
adc_start++;
ad_index=0;
ADIE=0;
ADIE=0;
ADON=0;
GO_nDONE=0;
}
}
*/
if(RC2IF==1)//串口2中断处理
{
rx_buf=RCREG2;
if(rx_buf == 0x3A) //界定符
{
com_data_num =0;
start_receive_data_flag = 1;
}
if(start_receive_data_flag==1)//开始接收界定符、地址、数据及结束符。
{
ser_buf[com_data_num] = rx_buf;
com_data_num++;
if(rx_buf == 0x0A)//0x0d 回车 为结束符
{
start_receive_data_flag = 0;
ser_process_data_flag = 1;
}
}
if(ser_process_data_flag==1)
{
rx_buf=(ser_buf[5]-0x30)*10+ ser_buf[6]-0x30+6;//提取数据长度
buf_comm=0;
for(index_comm=1;index_comm<=rx_buf;index_comm++)//计算校验和
buf_comm=buf_comm+ser_buf[index_comm];
//if(buf_comm==((ASCII(ser_buf[rx_buf+1]))*16+ASCII(ser_buf[rx_buf+2])))//比较校验和
{
//ser_com();//串口命令处理程序
Usart_Tm2(ser_buf,com_data_num);
}
ser_process_data_flag = 0;
}
}//end if(RC2IF==1)
}
以上程序未考虑容错,应加上:
if((RCSTA1bits.OERR==1)||(RCSTA1bits.FERR==1)){ 出错处理语句;}