⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can.c

📁 西安付立叶的基于at91rm9200的linux
💻 C
字号:
/****************************************Copyright (c)**************************************************
**                                  西安傅立叶电子有限公司
**                                     研    发    部
**                              http://www.FFTChina.com
**-----------------------------------------文件信息-----------------------------------------------------
**文   件   名: cantest.c
**创   建   人: 
**最后修改日期: 2005年6月30日
**描        述: CAN模块测试驱动程序(查询模式)
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif

#include "linux/types.h"
#include "linux/fs.h"
#include "linux/mm.h"
#include "linux/errno.h"
#include "linux/major.h"
#include "linux/blkdev.h"
#include  "linux/capability.h"
#include  "linux/smp_lock.h"

#include "linux/module.h"
#include "linux/version.h"
#include "linux/kernel.h"
#include "linux/config.h"

#include "asm/uaccess.h"
#include "asm/io.h"
#include "sja1000.h"
void   *can1addr;
void   *can0addr;
char   kernel_version[]=UTS_RELEASE;

unsigned int fftcan_major=0;
/*******************************************************
**  函数原形:setcanport(unsigned char chanal, unsigned char reg, unsigned char data1)
**	参数:    chanal : can通道号
**	          reg    : 寄存器地址
**	          data   : 要写入的数据
**  函数说明:向CAN写数据
/*******************************************************/
void setcanport(unsigned char chanal, unsigned char reg, unsigned char data1)
{
  
   if(!chanal)                     //是通道0
   {                              /*与IOREMAP配套的使用函数*/
        writeb(reg,can0addr+8);   //模拟ALE锁存地址,发地址信号;
        writeb(data1,can0addr);   //发送数据到地址
   }
    else
   {
        writeb(reg,can1addr+8);
        writeb(data1,can1addr);
   }
}
/*******************************************************
*函数原形:getcanport(unsigned char chanal, unsigned char reg)
*参数:        chanal  : can的通道号
*	            reg     :寄存器地址
*返回值 : 读出寄存器的值
*函数说明:读出寄存器的值
/*******************************************************/
unsigned char getcanport(unsigned char chanal, unsigned char reg)
{
    unsigned char temp;
    if(!chanal)
    { 
         writeb(reg,can0addr+8);     //先将地址发送出去,然后再读出此处的值;
         temp=readb(can0addr);
    }
    else
    {
        writeb(reg,can1addr+8);
        temp=readb(can1addr);
    }
    return (temp);
}
/*******************************************************
**  函数原形:ifgetdata(unsigned char chanal)
**	参数:    chanal : can通道号	          
**	返回值  :1:有可用数据
**            0:无可用数据
**  函数说明:判断can是否收到数据
/*******************************************************/
unsigned char ifgetdata(unsigned char chanal)
{
   unsigned char temp;
   if(((getcanport(chanal,REG_STATUS) & 0x01) != 1))
      temp = 1;
   else
      temp = 0;   
   return (temp);
}

/*******************************************************
*函数原形:read_fftcan(struct file *file, char *buf, size_t count,loff_t *f_pos)
*参数:        buf  : 传入该函数的数据缓冲区指针
*	           count:CAN的通道号
*返回值 : 0
*函数说明:读出接收到的CAN数据
/*******************************************************/

 int  read_fftcan(struct file *file, char *buf, size_t count,loff_t *f_pos)

{	
    int num,i;
    unsigned char chanal;
    unsigned char data[11] = {0};
    unsigned char dlc;
    buf = data;
    chanal = count;
    if((getcanport(chanal,REG_RxBuffer2) & 0x10) == 0)
    {
        dlc = (getcanport(chanal,REG_RxBuffer2) & 0x0f) + 2;
    } else {
	   dlc = 2;
    }
    for(i = 0; i < dlc ;i ++ )
    {
       *(buf + i) = getcanport(chanal,REG_RxBuffer1+i);
    }
    *(buf+i) = '\0';
    setcanport(chanal,REG_COMMAND,0x04);      //free receive memory
    setcanport(chanal,REG_COMMAND,0x08);      //free overflow memory
    return (0);

}

/*******************************************************
*函数原形:write_fftcan(struct file *file,const char *buf,size_t count,loff_t *f_pos)
*参数:    buf  : 传入该函数的数据缓冲区指针
*	       count:CAN的通道号
*返回值 : 0 说明成功写入
*函数说明:向CAN总线发送数据
/*******************************************************/

int  write_fftcan(struct file *file,const char *buf,size_t count,loff_t *f_pos)
{    
	unsigned char chanal;
	unsigned char temp ;
        int i;
	unsigned char dlc;
	chanal = count;                                           //在这里我们将count当成通道号来进行传递;
	temp = getcanport(chanal,REG_STATUS);
        while((getcanport(chanal,REG_STATUS) & 0x08) == 0)printk("send dat not finish!\n");         //检查发送缓冲区是否释放
	while((getcanport(chanal,REG_STATUS) & 0x04) == 0)printk("senddatreg locked\n");
	if((*(buf+1)&0x10) == 0)      
	{
	   dlc = (*(buf+1) & 0x0f) + 2; 
	}
	else 
	{
	   dlc = 2;
	}
	for(i = 0 ;i < dlc;i ++)
        {
           setcanport(chanal,REG_TxBuffer1+i,*(buf+i));
   	}
	setcanport(chanal,REG_COMMAND,0x01);                //将当前的信息发送出去
	do 
	{
	   temp = getcanport(chanal,REG_STATUS);           //如果发送完毕就退出循环
	   if((temp & 0x08) == 0x08)
           break;
        } while(1);                                        //If it is transmitted succeded?
        return (0);
	
}

/*******************************************************
*函数原形:FFT_init_can(unsigned char chanal,unsigned char ac,unsigned char am,unsigned char btr0,unsigned char btr1)
*参数:    chanel: CAN的通道号
           ac    : 验收代码寄存器的值
*	       am    :验收屏蔽寄存器的值
           btr0  : 波特率设置
           btr1  :
*返回值 : 0     :说明初始化成功
*函数说明:配置CAN总线
/*******************************************************/

void FFT_init_can(unsigned char chanal,unsigned char ac,unsigned char am,unsigned char btr0,unsigned char btr1)
{
	 unsigned char temp ;
     int i;
/*Config MOD&CR register进入复位模式,同时使能发送和接收中断*/
      do
      {  
         temp = 0x07;
         setcanport(chanal,REG_CONTROL,temp);
      } while((temp&0x01) != 0x01);
//测试波特率的值      
      setcanport(chanal, REG_BTR0, btr0);
      setcanport(chanal, REG_BTR1, btr1);
//设置验收代码寄存器的值
      setcanport(chanal,REG_ACR, ac);
//设置验收滤波寄存器的值
      setcanport(chanal,REG_AMR, am);
//设置输出控制寄存器的值	
      setcanport(chanal,REG_OCR, 0xda);
//设置始时钟分频寄存器的值
      setcanport(chanal, REG_CDR, 0x48);
//退出复位模式
      do
      {
	    setcanport(chanal, REG_CONTROL,0x06 );
	    temp = getcanport(chanal,REG_CONTROL);
      } while((temp & 0x01) != 0 );
      return 0;
}

/*******************************************************
*函数原形:open_fftcan(struct inode *inode,struct file *file)
*参数:               
*返回值 : 
*函数说明:
/*******************************************************/

int open_fftcan(struct inode *inode,struct file *file)
{   
    return 0;
}

/*******************************************************
*函数原形:open_fftcan(struct inode *inode,struct file *file)
*参数:               
*返回值 : 
*函数说明:
/*******************************************************/
int release_fftcan(struct inode *inode,struct file *file)
{
    return 0;
}
/***************************************************************************************************
*函数原形:ioctl_fftcan(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
*参数:    cmd  : 传入该函数的命令参数
*	           0  :判断是否CAN0收到可用数据
               1  :判断是否CAN1收到可用数据
               3  :初始化CAN0总线
               4  :初始化CAN1总线   
           arg :传入的参数
*返回值 :     0  :接收到有效数据 
               1  :没有接收到有效数据
               3  :成功初始化CAN0
               4  :成功初始化CAN1
               5  :无效的命令 
*函数说明:向CAN总线发送数据
/**************************************************************************************************/
static int ioctl_fftcan(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{
   unsigned char temp1,temp2;
   unsigned char ac,am,btr0,btr1,chanal;
   switch (cmd) 
   {
	case 0:                                  
	       temp1=ifgetdata(0);
           break;		
	case 1:                                  
           temp1=ifgetdata(1);
           break;		
	case 3:                                   
           chanal = 0;
           ac = (arg & 0xff000000) >> 24 ;         
           am = (arg & 0x00ff0000) >> 16;
           btr0 = (arg & 0x0000ff00) >> 8;
           btr1 = (arg & 0x000000ff) ;
           FFT_init_can(chanal,ac,am,btr0,btr1);  
	       temp1 = 3;
           break;
	case 4:                                  
           chanal = 1;
           ac = (arg & 0xff000000) >> 24 ;
           am = (arg & 0x00ff0000) >> 16;
           btr0 = (arg & 0x0000ff00) >> 8;
           btr1 = (arg & 0x000000ff) ;
           FFT_init_can(chanal,ac,am,btr0,btr1);
           temp1 = 4;
           break;
	default:
           temp1 = 5;
	   break;
  }
    return (temp1);
}
/**************************************
** 函数指针结构: file_operations
** 说明        :
***************************************/
struct file_operations fftcan_fops={

  	read :      read_fftcan,
    write:      write_fftcan,
	ioctl:	    ioctl_fftcan,
	open :	    open_fftcan,
    release:    release_fftcan,

};
/******************************************************
**  初始化模块:在加载模块时候调用
**  函数原形  : init_module(void)
**  说    明  :不用修改
******************************************************/
 int  init_module(void)
{
   int result;
   result=register_chrdev(0,"fftcan",&fftcan_fops);           //注册一个设备,得到驱动的主设备号
   if(result<0)
   {
      printk("cannot get fftcan major number\n");           //没有成功
      return result;
   }
   printk("congraulation,fftcan are successful registed\n");
   if(fftcan_major==0)
   {
      fftcan_major=result;                                 //记录下主设备号
   }
//映射物理地址到IO内存,可以让软件直接访问IO内存
    can0addr= ioremap(0x50800000,0x20);
/*将物理地址直接映射到IO内存*/
    can1addr=ioremap(0x50c00000,0x20);                    /*第一个参数是物理地址,第2个是映射的大小,因为CAN只有32字节的地址空间,所以就0X10*/
    return 0;
}
/*******************************************************
**  函数原形 : cleanup_module(void)
**  说明     : 在卸载模块时调用
******************************************************/
void cleanup_module(void)
{
   iounmap(can0addr);
   iounmap(can1addr);
   unregister_chrdev(fftcan_major,"fftcan");
   printk("exit fftcan\n");

}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -