利用GPIO自定协议完成数据传输


数模转换器DAC081S101是一款8位数字到模拟的微小功耗的转换器,通过对DAC模块中8位数据寄存器的控制来实现对DA模块功率的控制。

DAC模块的电路示意图如下图:

DAC芯片中数据传输具有自己的传输协议。由一个时钟信号线,一个使能线SYNC,一个数据线来完成数据的正确传输。




时钟周期信号的最大周期可达到30MHZ,在SYNC使能时,以每个周期的下降沿取数据线上的数据,高电平=1 低电平=0。DAC的模式位2位,数据位为8位。以16个周期为一完整数据传输周期。总工16位数据,前两位和后四位没有意义。




现在通过ARM上的GPIO引脚,模仿时钟信号和使能信号来完成数据的传输。闲话少说,直接上驱动代码:

/************************************************************************************************/
/* PROJECT:  				AT91SAM9260 DAC DRIVER  for Linux						            */
/* DATE:					2017-09-06															*/
/* author:					fluency									  							*/
/*																								*/
/************************************************************************************************/
#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
           //包含管脚操作的相关函数
#include 
       
       
         //包含创建设备文件的相关函数 #include 
        
          //模块加载头文件 #include 
         
           //内核头文件 #include 
          
            //内核初始化和退出函数 #include 
           
             //uint8_t 的头文件 #include 
            
              // udelay 的头文件 MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("DAC_driver for AT91SAM9260"); #define DAC_MAJOR 233 #define DAC_MINOR 0 #define DAC_NAME "dac_dev" #define DAC_SCLK AT91_PIN_PA4 #define DAC_SYNC AT91_PIN_PA5 #define DAC_DATA AT91_PIN_PA6 #define DELAY (1) #define DELAYTEST 500 static int debug = 1; #define DBG(format, args...) \ do { \ if (debug >= 1) \ printk(format, ##args); \ } while (0) static int dac_drv_release(struct inode *inode,struct file *file) { DBG("dac driver release!\n"); return 0; } //=================================================== // 初始化GPIO 端口方向 //=================================================== void init_DAC_port(void) { printk("init_dac_driver\r\n"); //clk引脚 设置为外部输出 初始为低 v16 at91_set_GPIO_periph(DAC_SCLK, 1); at91_set_gpio_output(DAC_SCLK, 0); //sync引脚 设置为外部输出 初始为高 v15 at91_set_GPIO_periph(DAC_SYNC, 1); at91_set_gpio_output(DAC_SYNC, 1); //数据引脚 设置为外部输出 初始为0 v14 at91_set_GPIO_periph(DAC_DATA, 1); at91_set_gpio_output(DAC_DATA, 0); //调试引脚 v13 at91_set_GPIO_periph(AT91_PIN_PC11, 1); at91_set_gpio_output(AT91_PIN_PC11, 1); } //========================================================= // .open 具体执行函数 //========================================================= static int dac_open(struct inode *inode,struct file *file) { printk("dac dac_open\r\n"); return 0; } //============================================================================ // .unlocked_ioctl 具体执行函数 // 参数2 cmd : 具体命令类型 // 参数3 arg : 具体数据类型 //============================================================================ static long dac_ioctl(struct file * file,unsigned int cmd,unsigned long arg) { int i; uint8_t data; printk("cmd==%d arg==%ld\r\n", cmd, arg); data = ( uint8_t)arg; printk("data==0x%02x\r\n", data); at91_set_gpio_value(DAC_SCLK, 0); //clk 拉低 at91_set_gpio_value(DAC_SYNC, 1); //sync 拉高 //sync 拉低 数据传输开始标志 at91_set_gpio_value(DAC_SYNC, 0); //sync 拉低 //时钟 at91_set_gpio_value(DAC_SCLK, 1); //clk 拉高 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 0); //clk 拉低 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 1); //clk 拉高 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 0); //clk 拉低 udelay(DELAY); //写模式 00 at91_set_gpio_value(DAC_SCLK, 1); //clk 拉高 at91_set_gpio_value(DAC_DATA, 0); //data 0 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 0); //clk 拉低 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 1); //clk 拉高 at91_set_gpio_value(DAC_DATA, 0); //data 0 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 0); //clk 拉低 udelay(DELAY); for (i = 7; i >= 0; i--) { at91_set_gpio_value(DAC_SCLK, 1); //clk 拉高 if ((data >> i) & 0x1) //先写高位 at91_set_gpio_value(DAC_DATA, 1); //data 1 else at91_set_gpio_value(DAC_DATA, 0); //data 0 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 0); //clk 拉低 udelay(DELAY); } at91_set_gpio_value(DAC_SCLK, 1); //clk 拉高 at91_set_gpio_value(DAC_DATA, 0); //数据 拉低 让数据位保持是0 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 0); //clk 拉低 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 1); //clk 拉高 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 0); //clk 拉低 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 1); //clk 拉高 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 0); //clk 拉低 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 1); //clk 拉高 udelay(DELAY); at91_set_gpio_value(DAC_SCLK, 0); //clk 拉低 //sync 拉高 数据传输结束标志 at91_set_gpio_value(DAC_SYNC, 1); //sync 拉高 return 0; } //======================================================== //定义file_operations 结构体 //======================================================== static struct file_operations io_drv_fops={ .owner = THIS_MODULE, .open = dac_open, .unlocked_ioctl = dac_ioctl, .release = dac_drv_release, }; //======================================================================================================= // 声明设备及注册 //======================================================================================================= struct cdev *my_cdev; struct class *my_class; static int __init dac_drv_init(void) { int err, devno = MKDEV(DAC_MAJOR, DAC_MINOR); //将主设备号与次设备号转换成dev_t类型 my_cdev = cdev_alloc(); //申请一个cdev内存 cdev_init(my_cdev, &io_drv_fops); //初始化cdev成员,建立cdev与file_operations之间的连接 my_cdev->owner = THIS_MODULE; err = cdev_add(my_cdev, devno, 1); //添加字符设备 if (err != 0) { printk("sleep dac device register failed!\n"); } my_class = class_create(THIS_MODULE, "sleep_class"); //为此设备创建一个类 if(IS_ERR(my_class)) { printk("Err: failed in creating class.\n"); return -1; } init_DAC_port(); //IO 初始化 device_create(my_class, NULL, devno, NULL, DAC_NAME "%d", DAC_MINOR ); //注册字符设备 return 0; } //======================================================== // 注销设备 //======================================================== static void __exit dac_drv_exit(void) { cdev_del(my_cdev); device_destroy(my_class, MKDEV(DAC_MAJOR, DAC_MINOR)); class_destroy(my_class); } module_init(dac_drv_init); //注册设备 module_exit(dac_drv_exit); //注销设备 
             
            
           
          
         
       
      
      
     
     
    
    
   
   


使用Logic分析仪来抓取模仿的信号图:


文笔很差,望各位游客见谅!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值