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

📄 rs485driver_v1.0.c

📁 基于ATML的arm的RS485驱动开发代码
💻 C
字号:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/ioctl.h>
#include <asm/arch/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/at91rm9200dk.h>
#include <asm/arch/AT91RM9200_TC.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/arch/AT91RM9200_USART.h>
#include <asm/arch/AT91RM9200_SYS.h>
#include <asm/types.h>
#include <asm/arch/memory.h>


#define  MAJOR_NUM   222
#define  DEVICE_NAME  "RS_485"

#define  RS485_IOC_MAGIC     0xd0
#define  RS485_MAXNR            2

#define  GET_CHAR        _IO(RS485_IOC_MAGIC,  0)
#define  GET_STRING      _IO(RS485_IOC_MAGIC,  1)
#define  PUT_CHAR        _IO(RS485_IOC_MAGIC,  1)
#define  PUT_STRING      _IO(RS485_IOC_MAGIC,  3)
#define  DMA_TO_DEVICE     1
#define  DMA_FROM_DEVICE   2

/*
unsigned long copy_to_user(void *to, const void *from,
unsigned long count);
unsigned long copy_from_user(void *to, const void *from,
unsigned long count);*/
/*dam_map_single函数原型*/
/*dma_addr_t dma_map_single(struct device *dev,void *buf,size_t size,enum dam_data_directions)*/


static int RS485_NUM[257];
unsigned char RxBuffer[256],TxBuffer[256];
unsigned char TestBuffer[]="My name is quzegang";
//unsigned char *pSendAddress=&TestBuffer[0];
//unsigned long pA;
//unsigned int *pF=(unsigned long)pV-0xc000000;
//pA=__virt_to_bus(TestBuffer);

AT91PS_SYS    SYS   =   (AT91PS_SYS)  AT91C_VA_BASE_SYS;
AT91PS_USART  US3   =   (AT91PS_USART)AT91C_VA_BASE_US3;




void PDC_Init(void)
{
	US3->US_RPR=0;
	US3->US_RCR=0;
	US3->US_TPR=0;
	US3->US_TCR=0;
	US3->US_RNPR=0;
	US3->US_RNCR=0;
	US3->US_TNPR=0;
	US3->US_TNCR=0;
	printk("KERNEL:The PDC init over!!\n");
}

void SetHighLevel_PB0(void)
{
    SYS->PIOB_PER|=(0x1<<0);     /*使能PB0于GPIO口模式*/
    SYS->PIOB_OER|=(0x1<<0);     /*使能PB0为GPIO输出模*/
    SYS->PIOB_SODR|=(0x1<<0);    /*输出高电平*/
}

void SetLowLevel_PB0(void)
{
    SYS->PIOB_PER|=(0x1<<0);     /*使能PB0于GPIO口模式*/
    SYS->PIOB_OER|=(0x1<<0);     /*使能PBO为GPIO输出模式*/
    SYS->PIOB_CODR|=(0x1<<0);    /*输出低电平*/
}


/*
**其中PA6/RXD3为RS485接受端,PA5/TXD3为RS485发送端,
**PB0/RTS3为接受和发送控制端口。PA5,PA6工作外设在第
**二功能,PB0工作在GPIO模式
*/
void US3_Init(void)
{
    
	SYS->PIOA_PDR|=((0x1<<5)|(0x1<<6));/*禁止PA5于PA6工作于GPIO模式*/
	SYS->PIOA_BSR|=((0x1<<5)|(0x1<<6));/*设置它们于B外设模式,即串口模式*/

	SYS->PMC_PCER|=(0x1<<9);           /*使能时钟*/
  
	US3->US_CR =0xcf;         /*使能串口接受与发送*/
	//US3->US_IDR=0xffffffff;   /*禁止所有中断*/
	US3->US_BRGR=33;          /*波特率设置*/
	US3->US_TTGR=0;           /*设置时间保护*/

	US3->US_PTCR=0x00000202;/*禁止PDC传输与接受请求(应该直接赋值)*/
  
	US3->US_MR=0x000008c1;   /*设置工作模式为485*/
	printk("KERNEL:The US3->RS485 init over!!!!\n");
}
    
    

void Delay(int Seconds)
{
	int i;
	for (i=0;i<Seconds;i++)
	{
		;
	}
}

char RS485_TxBuffer(void)
{
	PDC_Init();
	US3_Init();
	SetHighLevel_PB0();
	US3->US_CR=(0x1<<6);
	US3->US_PTCR|=(0x1<<8);
	US3->US_TPR=(unsigned long)(__virt_to_phys(&TestBuffer[0]));
	US3->US_TCR=20;
	US3->US_TNPR=0;
	US3->US_TNCR=0;
	Delay(900);
	printk("KERNEL:The UnSendNumber is %d __________\n",US3->US_TCR);
	
	return (US3->US_TCR);
}

void RS485_RxBuffer(void)
{
	//PDC_Init();
	US3_Init();
	SetLowLevel_PB0();
	US3->US_CR=(0x1<<4);
	US3->US_PTCR|=(0x1<<0);
	US3->US_RPR=(unsigned int)RxBuffer;
	US3->US_RCR=256;
	US3->US_RNPR=0;
	US3->US_RNCR=0;
	
	Delay(90000000);
}
	

int RS485_open(struct inode*,struct file*);
int RS485_release(struct inode*,struct file*);
/*int RS485_ioctl(struct inode*,struct file*, unsigned int, unsigned long);*/
int RS485_read(struct file*,char*,size_t ,loff_t *);
int RS485_write(struct file*,const char*,size_t,loff_t*);

static struct file_operations RS485_fops= {
	/*ioctl  :RS485_ioctl,*/
	owner  :THIS_MODULE,
	read   :RS485_read,
	write  :RS485_write,
	open   :RS485_open,
	release:RS485_release,
};

int __init RS485_init(void)
{
	int ret;

	ret = register_chrdev(MAJOR_NUM, DEVICE_NAME, &RS485_fops);
	if (ret < 0)
	{
		printk(KERN_WARNING "RS485: can't get major %d\n", MAJOR_NUM);
		return ret;
	}
	printk("now ,ok ,you can use\n");

	return 0;
}

void __exit RS485_exit(void)
{
	unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
}

module_init(RS485_init);
module_exit(RS485_exit);


int RS485_open(struct inode *inode,struct file *filp)
{
	int minor;
	minor=MINOR(inode->i_rdev);
    
	printk("Now begin ,good luck!\n");
	printk("**************************************\n");
	printk("*Now,We are going to test RS485:     *\n");
	printk("*Richisland,quzegang,07/09/24,NanJing*\n");
	printk("**************************************\n");
  
	RS485_NUM[minor]++;
	return 0;                                       /*succes*/
}

int RS485_release(struct inode *inode,struct file *filp)
{
	int minor;
	minor=MINOR(inode->i_rdev);
  
	if(RS485_NUM[minor])
	RS485_NUM[minor]--;
  
	return 0;
}

int RS485_read(struct file *filp,char *buf,size_t count ,loff_t *offp)
{
    int UnReadNumber;
	#ifdef DEBUG
		printk("\nmy_read is called.User buffer is %p,size is %d\n",buf,count);
	#endif
		if (verify_area(VERIFY_WRITE,buf,count)==-EFAULT)
		{
			printk("There are something wrong with read!!!!\n");
			return -EFAULT;
		}
		else
		{ 
			RS485_RxBuffer();
			UnReadNumber=copy_to_user(buf,RxBuffer,256);
			printk("The UnCopyNumber is %d\n",UnReadNumber);
			return UnReadNumber;
		}
}    

int RS485_write(struct file*filp,const char *buf,size_t count,loff_t *f_pos)
{
    int UnWriteNumber,UnSendNumber,i;
	#ifdef DEBUG
		printk("\nmy_write is called.User buffer is %p,size is %d\n",buf,count);
    #endif
		if (verify_area(VERIFY_WRITE,buf,count)==-EFAULT)
		{
			printk("There are something wrong with write\n");
			return -EFAULT;
		}
		else
		{	
			UnWriteNumber=copy_from_user(TxBuffer,buf,256);
			UnSendNumber=RS485_TxBuffer();
			printk("KERNEL:Data below is from user program:\n");
			for(i=0;i<256;i++)
			{
				printk("%d,",TxBuffer[i]);
			}
			printk("\nKERNEL:The UnWriteNumber is %d\n",UnWriteNumber);
			printk("KERNEL:now begin to write\n");/*为了传输完,实际在上面开始传输*/
			printk("KERNEL:The UnSendNumber is %d\n",UnSendNumber);
			return UnSendNumber;
		}
}


/*int RS485_ioctl(struct inode *inode,struct file *file, unsigned int cmd,unsigned long arg)

{
	int a,b,i;
	if (_IOC_TYPE(cmd)!=RS485_IOC_MAGIC)
    	{
		return -ENOTTY;
	}
	if (_IOC_NR(cmd)>=RS485_MAXNR)
    	{
		return -ENOTTY;
	}
  
	switch (cmd)
    	{
		case GET_CHAR:
        RS485_GetBuffer();
		a=copy_to_user((unsigned char*)arg,RxBuffer,256);
		while ( !(US3->US_CSR&(0x1<<9)) );
		Delay(8);
		
		for(i=0;i<256;i++)
			printk("I=%d\n",RxBuffer[i]);
		return (RS485_GetBuffer());
        	break;
        
		case PUT_CHAR:
			b=copy_from_user(TxBuffer,(unsigned char*)arg,256);
		
		for(i=0;i<256;i++)
			printk("F=%d\n",TxBuffer[i]);
		
        RS485_PutBuffer();
		Delay(8);		
		return (RS485_PutBuffer());
        	break;
        
		default: 
		return 0;
		break;
    }

}*/


MODULE_LICENSE("GPL");
MODULE_AUTHOR("Richisland ,nanjing ,Quzegang");
MODULE_DESCRIPTION("RS485 driver for AT91RM9200");

  
  






⌨️ 快捷键说明

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