PIC单片机论坛论坛展示区(非讨论区)(这个版块不能发新贴)『 乾龙盛开发板/实验板编程实例 』 → [QLdsPIC3]CAN总线[C30+dsPIC30F6014A]


  共有48232人关注过本帖树形打印

主题:[QLdsPIC3]CAN总线[C30+dsPIC30F6014A]

帅哥哟,离线,有人找我吗?
zhongruntian
  1楼 个性首页 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信 丐帮帮主
等级:老师(版主) 帖子:9899 积分:201298 威望:0 精华:32 注册:2005-3-13 12:01:00
[QLdsPIC3]CAN总线[C30+dsPIC30F6014A]  发帖心情 Post By:2008-10-7 16:34:00

-----------------------------------------------------

 下载信息  [文件大小:   下载次数: ]
图片点击可在新窗口打开查看点击浏览该文件:

-----------------------------------------------------

共两程序:

CANTX.C以发送数据为主

CANRX.C以接收数据为主



http://www.cevx.com/bbs/index.php
支持(1中立(0反对(0单帖管理 | 引用 | 回复 回到顶部
帅哥哟,离线,有人找我吗?
zhongruntian
  2楼 个性首页 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信 丐帮帮主
等级:老师(版主) 帖子:9899 积分:201298 威望:0 精华:32 注册:2005-3-13 12:01:00
  发帖心情 Post By:2008-10-7 16:35:00

//实验目的:CAN总线接收+LCD1602显示
//软件规划:
//          1。通过CAN总线接收另一主机发送过来的温度采集数据
//          2。接收到的数据转换后送1602LCD显示。
//          3。CAN模块采用模块C1,11位标识符的标准数据侦
//硬件规划:
//          1。拨玛开关S7全置ON
//          2。跳线J18全部接通
//          3。LCD1602插到座子上
//          4。接通CAN总线线缆

#include <p30f6014.h>             //dsPIC30F6014标准头文件
  _FOSC(0x0ffe5);                 //4倍频晶振,Failsafe 时钟关闭
  _FWDT(WDT_OFF);                 //关闭看门狗定时器
  _FBORPOR(PBOR_OFF & MCLR_EN);   //掉电复位禁止,MCLR复位使能。
  _FGS(CODE_PROT_OFF);            //代码保护禁止


#define rs LATBbits.LATB4          //定义LCD控制位(注意这里只能用LATB寄存器,不能直接用PORTB寄存器)
#define rw LATBbits.LATB5
#define e  LATBbits.LATB6
                      
unsigned char __attribute__((address(0x904))) TZ;    //转换后的温度值整数部分
unsigned char __attribute__((address(0x906))) TX;    //转换后的温度值小数部分
unsigned int  __attribute__((address(0x908))) wd;    //转换后的温度值BCD码形式
unsigned char __attribute__((address(0x9a0))) loop;  //LCD显示次数计数器

unsigned int buffer1;                                 //定义CAN接收缓冲单元  
unsigned int buffer2;
unsigned int buffer3;
unsigned int buffer4;
unsigned char __attribute__((address(0x930))) result[8]={0,0,0,'.',0,0,0,0};
unsigned long int i = 0;

//********************CAN模块初始化函数*************************
void initcan()
{
    C1CTRLbits.REQOP = 0x4; //请求进入配置模式
    while (C1CTRLbits.OPMODE!=0x4){}  //确认进入配置模式
    C1TX0CON = 0x0003;      //发送0邮箱配置,高优先级
    C1TX0SID = 0x0020;      //发送0标准标识符,11位
    C1TX0DLC = 0x01c0;      //发送0数据长度,8字节
    C1RX0CON = 0x0000;      //接收0邮箱配置
    C1RX0DLC = 0x0008;      //接收0数据长度,8字节
    C1RXF0SID = 0x0020;     //接收滤波器0标准标识符,11位
    C1RXM0SID = 0xffff;     //接收屏蔽0标准标识符
    C1CFG1bits.SJW=0;     //SJW=1 x TQ
    C1CFG1bits.BRP = 9;     //125K    
    C1CFG2 = 0x03Ac;        //SEG2PH=5;SEG1PH=6;PRSEG=4

    C1CTRLbits.REQOP = 0x0; //请求进入正常模式
    while (C1CTRLbits.OPMODE!=0x0){}  //确认进入正常模式
 return;

//****************延时函数**************************************
//延时函数(延时时间为(2+x)us)
void delay(  char x)
{
   unsigned char i;
   for(i=0;i<x;i++);
}

//*****************写一个字节数据函数***************************
//在电平发生改变后需要插入一段延时时间,否则LCD反应不过来。
void write(unsigned char x)
 {
  PORTD=x;                   //待显示数据送PORTD口
  delay(98);                  
  rs=1;                      //该字节数据为数据,而不是命令
  delay(98);
  rw=0;                      //此次操作为写,而不是读
  delay(98);
  e=0;                       //拉低使能信号
  delay(98);                   //保持使能信号为低一段时间
  e=1;                       //拉高使能信号,建立LCD操作所需要的上升沿
  delay(98);
 }

//******************LCD显示设置函数*****************************
//在电平发生改变后需要插入一段延时时间,否则LCD反应不过来。
void lcd_enable()
 {
   delay(98);
   rs=0;                     //该字节数据为命令,而不是数据
   delay(98);
   rw=0;                     //此次操作为写,而不是读
   delay(98);
   e=0;                      //拉低使能信号
   delay(98);                  //保持使能信号为低一段时间
   e=1;                      //拉高使能信号,建立LCD操作所需要的上升沿
   delay(98);
}

//******************系统初始化函数******************************
void init()
{
  TRISF=0X0000;                                 //先设置18B20口方向为输出
  TRISB=0X0000;                                 //设置B口方向为输出
  TRISD=0X0000;                                 //设置D口方向为输出
  IFS0bits.T1IF=0;                              //先清除定时器中断标志位
  PR1=0XFFFF;                                   //周期定最大
  T1CON=0X0020;                                 //分频比为1:64
  INTCON1=0x0000; 
  INTCON2=0x0000;    //关闭所有中断  
}

//*******************LCD初始化函数*******************************
void lcd_init()
 {
    PORTD=0X1;                 //清除显示
    lcd_enable();
    PORTD=0X38;                //8位2行5*7点阵
    lcd_enable();
    PORTD=0X0e;                //显示开,光标开,闪烁
    lcd_enable();
    PORTD=0X06;                //文字不动,光标右移
    lcd_enable();
 }
 
//*********************LCD显示函数*******************************
void display()
 { 
    PORTD=0X84;                //显示首地址
    lcd_enable();
    for(loop=0;loop<8;loop++)  //共显示8位
      {
        write(result[loop]);   //查表并送显示
        delay(100);            //插入一定延时
      }
 }

//******************启动温度转换函数*****************************
void get_temp()
{
int i;
result[0]=(TZ/100)+0x30;                 //整数百位
result[1]=((TZ%100)/10)+0X30;            //整数十位 
result[2]=((TZ%100)%10)+0X30;            //整数部分个位          
wd=0; 
if (TX & 0x80) wd=wd+5000;
if (TX & 0x40) wd=wd+2500;
if (TX & 0x20) wd=wd+1250;
if (TX & 0x10) wd=wd+625;                //以上4条指令把小数部分转换为BCD码形式            
result[4]=(wd/1000)+0x30;                //十分位
result[5]=((wd%1000)/100)+0x30;          //百分位
result[6]=((wd%100)/10)+0x30;            //千分位
result[7]=(wd%10)+0x30;                  //万分位
}

//**********************主函数***********************************
int main()
{
    init();                              //调用系统初始化函数
    lcd_init();                          //LCD初始化函数
    initcan();                           //调用CAN初始化函数
     buffer1=buffer2=buffer3=buffer4=0;
 while(1)
 {   
      while(C1RX0CONbits.RXFUL==0);     //等待接收到数据
   buffer1 = C1RX0B1;          //读取接收到的数据
         buffer2 = C1RX0B2;
         buffer3 = C1RX0B3;
         buffer4 = C1RX0B4;
            C1RX0CONbits.RXFUL = 0;
         TZ=buffer1;                
            TX=buffer2;
            get_temp();                 //调用温度转换函数
            display();                  //调用结果显示函数
 }
}



http://www.cevx.com/bbs/index.php
支持(0中立(2反对(1单帖管理 | 引用 | 回复 回到顶部
帅哥哟,离线,有人找我吗?
zhongruntian
  3楼 个性首页 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信 丐帮帮主
等级:老师(版主) 帖子:9899 积分:201298 威望:0 精华:32 注册:2005-3-13 12:01:00
  发帖心情 Post By:2008-10-7 16:37:00

//实验目的:熟悉CAN总线的发送功能+DS18B20温度采集
//软件规划:
//          1。DS18B20定时采集温度
//          2。温度采集时间间隔用T1定时器控制
//          3。采集到的温度通过CAN总线送另一主机处理
//硬件规划:
//          1。拨码开关S7全置ON
//          2。跳线J5接通
//          3。DS18B20插放在U3上面
//          4。接通CAN总线线缆

#include <p30f6014.h>             //dsPIC30F6014标准头文件
  _FOSC(0x0ffe5);                 //4倍频晶振,Failsafe 时钟关闭
  _FWDT(WDT_OFF);                 //关闭看门狗定时器
  _FBORPOR(PBOR_OFF & MCLR_EN);   //掉电复位禁止,MCLR复位使能。
  _FGS(CODE_PROT_OFF);            //代码保护禁止

unsigned long int i = 0;

#define  uch unsigned char                     //给unsigned char起别名 uch
# define DQ PORTFbits.RF6                      //定义18B20数据端口
# define DQ_DIR TRISFbits.TRISF6               //定义18B20D口方向寄存器
# define DQ_HIGH() DQ_DIR =1                   //设置数据口为输入
# define DQ_LOW() DQ = 0; DQ_DIR = 0           //设置数据口为输出

#define rs LATBbits.LATB4          //定义LCD控制位(注意这里只能用LATB寄存器,不能直接用PORTB寄存器)
#define rw LATBbits.LATB5
#define e  LATBbits.LATB6
                       
unsigned char __attribute__((address(0x900))) TLV;   //采集到的温度高8位
unsigned char __attribute__((address(0x902))) THV;   //采集到的温度低8位
unsigned char __attribute__((address(0x904))) TZ;    //转换后的温度值整数部分
unsigned char __attribute__((address(0x906))) TX;    //转换后的温度值小数部分
unsigned int  __attribute__((address(0x908))) wd;    //转换后的温度值BCD码形式
unsigned char __attribute__((address(0x9a0))) loop;  //LCD显示次数计数器

//**********************CAN总线初始化*************************
void initcan()
{
    C1CTRLbits.REQOP = 0x4; //请求进入配置模式
    while (C1CTRLbits.OPMODE!=0x4){}  //确认进入配置模式
    C1TX0CON = 0x0003;      //发送0邮箱配置
    C1TX0SID = 0x0020;      //发送0标准标识符,11位
    C1TX0DLC = 0x01c0;      //发送0数据长度,8字节
    C1RX0CON = 0x0000;      //接收0邮箱配置
    C1RX0DLC = 0x0008;      //接收0数据长度,8字节
    C1RXF0SID = 0x0020;     //接收滤波器0标准标识符,11位
    C1RXM0SID = 0xffff;     //接收屏蔽0标准标识符

   C1CFG1bits.SJW=0;  //SJW=1 x TQ
   C1CFG1bits.BRP = 9;      //125K  
   C1CFG2 = 0x03Ac;         //SEG2PH=5;SEG1PH=6;PRSEG=4

    C1CTRLbits.REQOP = 0x0; //请求进入正常模式
    while (C1CTRLbits.OPMODE!=0x0){}  //确认进入正常模式
 return;
}     


//**********************延时函数**************************
//延时函数(延时时间为(2+x)us)
void delay(  char x)
{
   unsigned char i;
   for(i=0;i<x;i++);
}

//********************系统初始化函数**********************
void init()
{
  TRISF=0X0000;                                 //先设置18B20口方向为输出
  TRISB=0X0000;                                 //设置B口方向为输出
  TRISD=0X0000;                                 //设置D口方向为输出
  IFS0bits.T1IF=0;                              //先清除定时器中断标志位
  PR1=0XFFFF;                                   //周期定最大
  T1CON=0X0020;                                 //分频比为1:64

  INTCON1=0x0000; 
  INTCON2=0x0000;                             //关闭所有中断  
}


//******************复位DS18B20函数*****************************
//主控制器(dsPIC30F6014A)先拉低总线480us,然后释放总线回到高电平
//18B20检测到上升沿后先等待15-60us,然后拉低总线做为复位的应答信号
//主控制器释放总线后到复位结束时间应为480US
reset(void)
{
  char presence=1;
  while(presence)
  {
    DQ_LOW() ;                                //主机拉至低电平
    delay(100);                        
    delay(100);  
    delay(100);  
    delay(100);
    delay(78);                                //以上5条共延时480us
    DQ_HIGH();                                //释放总线等电阻拉高总线,并保持15~60us
    delay(38);                                //延时40us       
    if(DQ==1) presence=1;                     //没有接收到应答信号,继续复位
    else presence=0;                          //接收到应答信号
    delay(100);                        
    delay(100);  
    delay(100);  
    delay(100);
    delay(38);                                //以上5条共延时440us
   }
  }

//****************写18b20写字节函数*****************************
//主控制器写数据1:先把总线拉低,然后在15us内释放总线
//主控制器写数据0:把总线拉低至少60us
//写一位数据至少需要60us
//两位数据之间至少延时1us
void write_byte(uch val)
{
 uch i;
 uch temp;
 for(i=8;i>0;i--)
 {
   temp=val&0x01;                            //最低位移出
   DQ_LOW();
   delay(3);                                 //保持拉低5us
   if(temp==1)  DQ_HIGH();                   //如果写1,拉高电平
   delay(58);                                //延时60us
   DQ_HIGH();
   delay(1);                                 //在两位之间插入3us延时
   val=val>>1;                               //右移一位
  }
}

//****************18b20读字节函数********************************
//主控制器把总线拉低至少1US,然后释放
//主控制器读数据1:18B20保持总线状态不变
//主控制器读数据0:18B20检测到总线拉低后继续拉低总线至少60ms
//主控制器在拉低总线后的15us读取总线上的状态
//读取1位数据至少需要60us
uch read_byte(void)
{
 uch i;
 uch value=0;                                //读出温度
 for(i=8;i>0;i--)
 {
   value>>=1;
   DQ_LOW();
   delay(1);                                //保持总线拉低3us
   DQ_HIGH();                               //拉至高电平
   delay(5);                                //释放总线后保持7us再读取数据
   if(DQ) value|=0x80;
   delay(48);                               //延时50us,保证每1位的60us延时
  }
  return(value);
}

//*****************启动温度转换函数***************************
void get_temp()
{
int i;
DQ_HIGH();                              
reset();                                 //复位等待从机应答
write_byte(0XCC);                        //忽略ROM匹配
write_byte(0X44);                        //发送温度转化命令 
for(i=0;i<8;i++)
    {
       
      delay(98);                         //确保温度转换完成所需要的时间
    }
reset();                                 //再次复位,等待从机应答
write_byte(0XCC);                        //忽略ROM匹配
write_byte(0XBE);                        //发送读温度命令
TLV=read_byte();                         //读出温度低8
THV=read_byte();                         //读出温度高8位
DQ_HIGH();                               //释放总线
TZ=(TLV>>4)|(THV<<4)&0X3f;               //温度整数部分
TX=TLV<<4;                               //温度小数部分
}

//************************主函数********************************
int main(void)
{
   init();                              //调用系统初始化函数
   initcan();

   LATDbits.LATD0=1;
   LATDbits.LATD1=0;
   while(1)
     {
       TMR1=0XC2F6;                     //定时器初值
       T1CONbits.TON=1;                 //启动定时器
       while(!IFS0bits.T1IF);           //等待0.1s定时到
       IFS0bits.T1IF=0;
       get_temp();                      //调用温度转换函数
     
       C1TX0B1 = TZ;                   
       C1TX0B2 = TX;
       C1TX0B3 = 0x5A5A;                //B3跟B4四字节数据无效,也可做效验用
       C1TX0B4 = 0xa5a5;
       C1TX0CONbits.TXREQ = 1;          //启动发送
       while (C1TX0CONbits.TXREQ==1){} //等待发送完成
       for (i=0;i<2;i++){}
     }
}
  



http://www.cevx.com/bbs/index.php
支持(2中立(2反对(1单帖管理 | 引用 | 回复 回到顶部
帅哥哟,离线,有人找我吗?
snowwolf
  4楼 个性首页 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:小学六年级 帖子:29 积分:906 威望:0 精华:0 注册:2008-7-4 10:00:00
  发帖心情 Post By:2009-9-10 15:12:00

3Q图片点击可在新窗口打开查看

支持(2中立(2反对(0单帖管理 | 引用 | 回复 回到顶部
帅哥哟,离线,有人找我吗?
surf131
  5楼 个性首页 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:老师(版主) 帖子:1811 积分:37153 威望:0 精华:4 注册:2009-11-8 16:53:00
  发帖心情 Post By:2010-10-15 21:35:00

偶然翻到了这么有用的帖子!谢谢,谢谢钟版!


呼唤创造力!召唤创造力!可惜没权传唤创造力.......
支持(2中立(1反对(1单帖管理 | 引用 | 回复 回到顶部
帅哥哟,离线,有人找我吗?
wujianwxxj
  6楼 个性首页 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:小学四年级 帖子:21 积分:668 威望:0 精华:0 注册:2011-3-4 12:23:00
  发帖心情 Post By:2011-3-13 9:18:00

正准备写个CAN接收的程序,学习了

支持(1中立(2反对(3单帖管理 | 引用 | 回复 回到顶部
帅哥哟,离线,有人找我吗?
wangluojisuan
  7楼 个性首页 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:小学一年级 帖子:5 积分:303 威望:0 精华:0 注册:2011-9-14 9:50:00
  发帖心情 Post By:2011-10-24 15:10:00

学习CAN总线能用得到!!

支持(2中立(1反对(1单帖管理 | 引用 | 回复 回到顶部

返回版面帖子列表(如果下面的回复窗口不可输入,请点“代码模式”再点“设计模式”)

[QLdsPIC3]CAN总线[C30+dsPIC30F6014A]








签名    小提示:如果上面的回复窗口不可输入,请先点“代码模式”然后再点“设计模式”,然后就可输入回复内容了
Google 全部 本站