总线型运动控制系统 传统运动控制系统中常以脉冲和模拟量作为控制信号,并将控制信号发送到电机驱动器中,再由电机驱动器驱动电机运行。得益于总线技术的发展,运动控制器厂家将总线技术应用运动控制器中。上位机通过总线将运动参数传送至电机驱动器,再由电机驱动器驱动电机运行。常见的总线技术有ProfiNet,ProfiBus,EhertCA T,RTEX,CCLINK等等。 总线型运动控制系统相对传统的运动控制系统有诸多优点。 1.接线简化。 在传统运动控制系统中,上位机与电机驱动器通过大量的数字量或者模拟量IO连接,以发送控制信号和接受反馈信号。这样会使接线数量增加,接线出错的几率比较大,线材成本上升,布线时间长而复杂。在总线型运动控制系统中,上位机的总线通讯接口可以通过线性拓扑方式连接多个支持总线通讯的电机驱动器。 2.拥有故障自诊断特性。 传统型运动控制系统中的上位机与电机控制器的信息交换是通过有限的IO进行的。能获取的信息是极有限。总线型运动控制系统拥有多种诊断功能。可以实时监控电机的运行状态,实时获取运行状态的信息。如果电机运行有异常,其相应的电机驱动器可通过总线向上位机发送异常信息。如线缆短路或短路、接头接触不良,电压异常等物理层诊断。 3.方便调试。 总线型运动控制系统,可以通过上位应用软件监控和调整各电机驱动器节点的参数。不用通过各电机驱动器的显示面板调整参数。 4.可靠性高 传统运动控制系统的中脉冲信号和模拟量信号,容易受到电磁干扰,可导致信号失真。总线型运动控制系统数字式通讯方式,无信号漂移问题。 总线型运动控制系统应用示例:3S总线控制系统通过EherCAT总线控制7轴运动。3S 总线系统可以控制多达128个轴,支持复杂插补运算;可控制多达10台不同类型的机器人;提供多达8192点数字量或模拟扩展功能;可接入视觉系统实现定位功能。
PCI总线驱动的机制 1.总线子系统初始化 系统初始化时会调用 ■void __init driver_init(void) { 。。。。。。 buses_init(); 。。。。。。 } ■ ★I nclude/linux/kobject.h #define decl_subsys(_name,_type,_uevent_ops) \ struct subsystem _name##_subsys = { \ .kset = { \ .kobj = { .name = __stringify(_name) }, \ .ktype = _type, \ .uevent_ops =_uevent_ops, \ } \ } ★ Drivers/base/bus.c static struct kobj_type ktype_bus = { .sysfs_ops = &bus_sysfs_ops, }; ★ static decl_subsys(bus, &ktype_bus, NULL); bus_subsys={ .ket = { .kobj = { .name = “bus”, .ktype = &ktype_bus, .uevent_ops = NULL, } } ★int __init buses_init(void) { return subsystem_register(&bus_subsys); }
在buses_init中调用subsystem_register时,bus_subsys作为sysfs root 目录下的项被建立(因为其kset.kobj.parent的值为NULL) ■pci总线初始化 ★struct bus_type pci_bus_type = { .name = "pci", .match = pci_bus_match, .uevent = pci_uevent, .probe = pci_device_probe, .remove = pci_device_remove, .suspend = pci_device_suspend, .suspend_late = pci_device_suspend_late, .resume_early = pci_device_resume_early, .resume = pci_device_resume, .shutdown = pci_device_shutdown, .dev_attrs = pci_dev_attrs, }; ★struct device_attribute pci_dev_attrs[] = { __ATTR_RO(resource), __ATTR_RO(vendor), __ATTR_RO(device), __ATTR_RO(subsystem_vendor), __ATTR_RO(subsystem_device), __ATTR_RO(class), __ATTR_RO(irq), __ATTR_RO(local_cpus), __ATTR_RO(modalias), #ifdef CONFIG_NUMA __ATTR_RO(numa_node), #endif __ATTR(enable, 0600, is_enabled_show, is_enabled_store), __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), broken_parity_status_show,broken_parity_status_store), __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store), __ATTR_NULL, }; ★static int __init pci_driver_init(void) { return bus_register(&pci_bus_type); } postcore_initcall(pci_driver_init); 通过postcore_initcall声明,使pci_driver_init函数被链接到.initcall.init段。这个段的函数在初始化时由static void __init do_initcalls(void)函数调用。最终系统在初始化线程static int __init
linux内核学习---总线,设备,驱动 Linux 设备模型中三个很重要的概念就是总线,设备,驱动.即 bus,device,driver,而实际上内核中也定义了这么一些数据结构,他们是 struct bus_type,struct device,struct device_driver,这三个重要的数据结构都来自一个地方,include/linux/device.h.我们知道总线有很多种,pci总线,scsi 总线,usb 总线,所以我们会看到Linux 内核代码中出现pci_bus_type,scsi_bus_type,usb_bus_type,他们都是 struct bus_type 类型的变量.而struct bus_type 结构中两个非常重要的成员就是 struct kset drivers 和 struct kset devices。kset 和另一个叫做 kobject 正是 Linux Kernel 2.6 中设备模型的基本元素。 这里我们只需要知道,drivers 和 devices 的存在,让struct bus_type 与两个链表联系了起来,一个是devices 的链表,一个是 drivers 的链表,也就是说,知道一条总线所对应的数据结构,就可以找到这条总线所关联的设备有哪些,又有哪些支持这类设备的驱动程序. 而要实现这些,就要求每次出现一个设备就要向总线汇报,或者说注册,每次出现一个驱动,也要向总线汇报,或者说注册.比如系统初始化的时候,会扫描连接了哪些设备,并为每一个设备建立起一个 struct device 的变量,每一次有一个驱动程序,就要准备一个 struct device_driver 结构的变量.把这些变量统统加入相应的链表,device 插入 devices 链表,driver 插入 drivers 链表. 这样通过总线就能找到每一个设备,每一个驱动。 struct bus_type 中为 devices 和 drivers 准备了两个链表,而代表 device 的结构体 struct device 中又有两个成员,struct bus_type *bus 和 struct device_driver *driver。同样,代表driver 的结构体 struct device_driver 同样有两个成员,struct bus_type *bus 和 struct list_head devices。struct device 和struct device_driver 的定义和 struct bus_type 一样,在 include/linux/device.h 中。凭一种男人的直觉,可以知晓,struct device 中的 bus 记录的是这个设备连在哪条总线上,driver 记录的是这个设备用的是哪个驱动,反过来,struct device_driver 中的 bus 代表的也是这个驱动属于哪条总线,devices 记录的是这个驱动支持的那些设备,没错,是 devices(复数),而不是 device(单数),因为一个驱动程序可以支持一个或多个设备,反过来一个设备则只会绑定给一个驱动程序。 上面是理论知识,下面我们具体以展讯平台的I2C设备重力加速度传感器MC3XXX驱动为例进行实例分析: 1.首先在Board-sp7715ga.c文件中通过sc8810_add_i2c_devices函数(其实是i2c_register_board_info函数)将指定的I2C设备( MC3XXX_ACC_I2C_NAME, MC3XXX_ACC_I2C_ADDR---包括设备名和设备地址)申请一个I2C struct device 结构,并且挂入I2C总线中的devices 链表中来。 注意:该device挂入devices链表的操作会先于I2C设备驱动加载的操作被执行。i2c_register_board_info函数对此进行了特别说明:
在总结的过程中参考了下面一些资料,在此表示感谢: [1]