本帖最后由 guaxian 于 2013-8-6 14:18 编辑
求PIC18F25K80,USB转CAN的例程,或者有没有这款单片机写的相关代码呢,本人菜鸟求指导啊~有个代码在这,看得也是一知半解啊~求高手帮忙再注释下,讲解下,目前硬件还没做好,只是编译通过了~还没试过收发数据啊。。。。。
#include <htc.h>
//振荡器为HS(12M),系统振荡器时钟转换选择禁止,故障保护时钟监视器禁止,不使用扩展指令集,直接使用振荡器高功耗,禁止低功耗稳压器
__CONFIG(1,RETEN_OFF & INTOSCSEL_LOW & SOSCSEL_DIG & XINST_OFF & FOSC_HS1 & PLLCFG_OFF & FCMEN_OFF & IESO_OFF);
//监视定时器WDT禁止watchdog,掉电锁定复位硬件使能欠压复位(仅硬件)电压为2.0V,上电定时器使能
__CONFIG(2,PWRTEN_OFF & BOREN_SBORDIS & BORV_2 & BORPWR_ZPBORMV & WDTEN_OFF & WDTPS_256); //
//CANTX/CANRX引脚在RB2/RB3上,MSSP V3 7位地址掩码模式,MCLR使能
__CONFIG(3,CANMX_PORTB & MSSPMSK_MSK7 & MCLRE_ON); //
//使能RB6、RB7为专用调试器接口,堆栈溢出复位使能,低压编程禁止
__CONFIG(4,STVREN_OFF & BBSIZ_BB2K);
//程序存储区、数据EEPROM,引导区都无代码保护,正式发布时要改成保护状态。
__CONFIG(5,CP0_OFF & CP1_OFF & CP2_OFF & CP3_OFF & CPB_OFF & CPD_OFF);
//程序存储区、数据EEPROM,引导区、配置寄存器都无写保护
__CONFIG(6,WRT0_OFF & WRT1_OFF & WRT2_OFF & WRT3_OFF & WRTC_OFF & WRTB_OFF & WRTD_OFF);
//程序存储区、引导区都无表读保护
__CONFIG(7,EBTR0_OFF & EBTR1_OFF & EBTR2_OFF & EBTR3_OFF & EBTRB_OFF);
/*全局变量定义*/
char CAN_TX_Adress_H; //CAN高地址标识符,应与接收方标识符相同
char CAN_TX_Adress_L; //CAN低地址标识符
// 设置接收邮箱0标识符
char CAN_RX_Adress_H; //CAN高地址标识符
char CAN_RX_Adress_L; //CAN低地址标识符,应与发送方标识符相同
unsigned char CanRecFlag; //=1接收到自身的CAN 数据,=0未接收到数据
unsigned char Counter; //计数器
unsigned char UartFlag; //串口数据接收标志
unsigned char Uartdata[8]; //接收数据,PC-MCU
unsigned char Senddata[8]; //发送数据,MCU-PC
/*函数声明*/
#define Fosc 12000000 //晶振为12MHZ
#define BAUDRATE 9600 //波特率为9600(uart串口)
void PicInit(void); //芯片初始化
void CANInit(void); //自带CAN口初始化
void interrupt HI_ISR(void);
void interrupt low_priority LOW_ISR(void);
void Delay(unsigned int time); //延时函数
void UartInt(void); //串口初始化程序
/*芯片初始化程序*/
void PicInit(void)
{
PORTA = 0x00; //清除PORTA完成初始化
LATA = 0x00; //清除数据输出锁存
PORTB = 0x00;
LATB = 0x00;
PORTC = 0x00;
LATC = 0x00;
ADCON1 = 0x0F; //关闭模拟通道,使之为数字通道
UartFlag = 0; //计数器清0
CanRecFlag =0;
Counter = 0;
}
/*串口初始化程序(与PC通讯)*/
void UartInt(void)
{
TRISC6 = 0; //设置UART端口,RC6是数据发送
TRISC7 = 1; //RC7是数据接收
BAUDCON1=0x00; //8位波特率发生器,SPBRGH值忽略
SPBRG1 = ((Fosc/BAUDRATE)/64)-1; //值约为(31)8位,异步,低速 (波特率设置寄存器)
TXSTA1 = 0b00100010;//异步模式,8位发送,发送使能,低速
RCSTA1 = 0b10010000;//使能串口,8位接收,使能连续接收
RCIP = 0; //EUSATR串口接收设置为低优先级中断
RCIE = 1; //允许EUSART接收中断
TXIE = 0; //禁止发送中断
CREN1 = 1; //允许串口接收数据
PIR1bits.RCIF = 0; //串口接收中断标志清零
}
/*自带CAN口初始化*/
void CANInit(void)
{
TRISB2 = 0; //设置CANRX-RB3输入
TRISB3 = 1; //设置CANTX-RB2输出
CANCON = 0x80; //请求配置方式(0x00请求进入正常模式)
while((CANSTAT&0x80)==0); //等待进入配置模式(若=0x40进入自测模式)
// 设置CAN波特率125kbps,在Fosc=12MHz时,Tbit=8us,假设BRP=05h
// 则Tq=[2*(1+BRP)]/Fosc=2*(1+5)/(12MHz)=1us
// normal bit rate=8Tq,SJW=00,Sync_Seg=1Tq,Prog_Seg=1Tq
// Phase_Seg1=3Tq,Phase_Seg2=3Tq
// 位时间=(1+1+3+3)=8Tq
// 总线过滤器用于唤醒
BRGCON1 = 0x05; // SJW同步跳转宽度SJW=00(1Tq),BRP=05h波特率预分频比为5
BRGCON2 = 0x90; // 配置相位缓冲段1 Phase_Seg1为3Tq,传播时间为1 Prog _SegTq
BRGCON3 = 0x42; // 配置相位缓冲段2为3Tq,使用CAN总线线路滤波器来唤醒
//设置发送邮箱0标识符 :00110011111=0x019F
CAN_TX_Adress_H=0x33; //CAN高地址标识符,应与接收方标识符相同
CAN_TX_Adress_L=0xe0; //CAN低地址标识符
CAN_TX_Adress_L=CAN_TX_Adress_L&0xe0;
// 设置接收邮箱0标识符 :10011001010=0x04CA
CAN_RX_Adress_H=0x99; //CAN高地址标识符
CAN_RX_Adress_L=0x55; //CAN低地址标识符,应与发送方标识符相同
CAN_RX_Adress_L=CAN_RX_Adress_L&0xe0;
//设置发送邮箱0标识符号和发送的数据
TXB0CON = 0x03; //设置TXB0 发送最高优先级3
TXB0SIDH = CAN_TX_Adress_H; //
TXB0SIDL = CAN_TX_Adress_L&0xe0; //
TXB0DLC = 0x08; //设置数据缓冲区长度为8个字节
TXB0D0 = 0x01; //第2个字节 // 第一个字节用来区分是发送到那个can口的标记
TXB0D1 = 0x02; //第3个字节
TXB0D2 = 0x03; //第4个字节
TXB0D3 = 0x04; //第5个字节
TXB0D4 = 0x05; //第6个字节
TXB0D5 = 0x06; //第7个字节
TXB0D6 = 0x07; //第8个字节
TXB0D7 = 0x08; //第9个字节
//设置接收邮箱0的标识符和初始化数据
RXB0SIDH = CAN_RX_Adress_H; //
RXB0SIDL = CAN_RX_Adress_L&0xe0; //
RXB0CON = 0x20; //仅接收带有标准标示符的有效报文
RXB0DLC = 0X08; //设置接收缓冲器0的数据区长度
RXB0D0 = 0X00; //初始化接收缓冲器0的数据区数据
RXB0D1 = 0X00;
RXB0D2 = 0X00;
RXB0D3 = 0X00;
RXB0D4 = 0X00;
RXB0D5 = 0X00;
RXB0D6 = 0X00;
RXB0D7 = 0X00;
//*******初始化接收滤波器0和接收屏蔽*****************/
RXF0SIDH=CAN_RX_Adress_H;
RXF0SIDL=CAN_RX_Adress_L&0xe0;//高3位为标识符低3位,低5位是配置 */
RXM0SIDH=0Xff;
RXM0SIDL=0Xe0; //11个1表示接收11位标识符进行滤波,标识符不同不接收
//初始化CAN模块的I/O控制寄存器,当“隐性”时,CANTX引脚驱动到高阻状态,禁止CAN捕捉
CIOCON = 0x00;
CANCON = 0x00; //请求正常方式
while((CANSTAT&0x80) != 0); //等待进入正常模式
//初始化CAN的中断,PIR3为CAN的外围中断标志寄存器
PIR5bits.RXB0IF = 0; //CAN接收缓冲器0中断标志位清零
PIE5bits.RXB0IE = 1; //使能CAN接收缓冲器0的接收中断
IPR5bits.RXB0IP = 1; //接收缓冲器0的接收中断为高优先级
NOP();
}
/*中断函数*/
void interrupt HI_ISR(void)
{
if(PIR5bits.RXB0IF ==1 )
{
CanRecFlag = 1; //自带can接收到CAN数据
PIR5bits.RXB0IF = 0; //清接收中断标志
RXB0CONbits.RXFUL = 0; //打开接收缓冲器,使可以接收新信息
}
}
void interrupt low_priority LOW_ISR(void)
{
if((PIE1bits.RCIE == 1)&&(PIR1bits.RCIF == 1)) //判断是不是串口中断 ,RCIF=1 接收缓冲区RCREG1已满
{
Uartdata[Counter]=RCREG;
Counter++;
if(Counter>7) //8位有效数据
{
Counter=0;
UartFlag=1; //有串行数据接收
}
}
}
/*延时函数*/
void Delay(unsigned int time)
{
unsigned int i;
for(i=0;i<time;i++)
{;}
}
/*串口接收转发到Can函数*/
void Com2Can(void)
{
TXB0CON=TXB0CON&0xf7; //bit3:TXREQ=0, 关请求发送
UartFlag=0; //清标志
TXB0D0=Uartdata[0]; //CAN发送数据更新(用串口接收来的数据)
TXB0D1=Uartdata[1];
TXB0D2=Uartdata[2];
TXB0D3=Uartdata[3];
TXB0D4=Uartdata[4];
TXB0D5=Uartdata[5];
TXB0D6=Uartdata[6];
TXB0D7=Uartdata[7];
TXB0CON=TXB0CON|0x08; //请求发送,TXB0CONbits.TXREQ=1
while(TXB0CONbits.TXREQ); //等待发送完毕
// Delay(10000);
}
/*Can接收转发到串口函数*/
void Can2Com(void) //接收数据返回PC机
{
unsigned char i;
Senddata[0]=RXB0D0;
Senddata[1]=RXB0D1;
Senddata[2]=RXB0D2;
Senddata[3]=RXB0D3;
Senddata[4]=RXB0D4;
Senddata[5]=RXB0D5;
Senddata[6]=RXB0D6;
Senddata[7]=RXB0D7;
RCEN=0; //接收禁止
TXEN1=1; //使能串口发送
for(i=0;i<8;i++) //串口数据发送
{
TXREG = Senddata;
while(TXSTA1bits.TRMT == 0);
// Delay(100);
}
TXEN1=0; //禁止数据发送
RCEN=1; //接收使能
}
/*Main函数*/
void main(void)
{
INTCON = 0x00; //禁止所有中断
PicInit(); //芯片状态初始化
CANInit(); //芯片自带can口初始化
UartInt(); //串口初始化
IPEN = 1; //使能中断优先级
INTCON |= 0xC0; //开放所有高低优先级中断
TXB0CONbits.TXREQ = 0; //禁止CAN发送
while(1)
{
//串口接收到数据转发
if(UartFlag) //接收到串口数据
{
UartFlag=0;
Com2Can();
}
//CAN 接收到数据转发
if(CanRecFlag) //接收到CAN总线数据
{
CanRecFlag=0;
Can2Com();
}
}
}
|