微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 高清视频监控中的I2C总线云台电机控制设计

高清视频监控中的I2C总线云台电机控制设计

时间:04-20 来源:3721RD 点击:



图2 I2c驱动架构图

(2)云台电机驱动设计

根据Linux2.6.32的驱动分层设计,驱动的第一层和第二层在Linux-2.6.32中以及集成了成熟驱动,分别位于Linux源代码目录下的\drivers\i2c\i2c-core.c和\drivers\i2c\busses\davinci.c中,本文重点讲述第三层和第四层驱动程序的设计。

驱动设计采用字符设备方式来实现,motor_I2C_devInit()和motor_I2C_devExit()实现驱动的初始化以及退出,初始化最后调用cdev_add()实现字符设备的添加,添加过程中通过完善file_operations的结构体,填充了。open = I2C_devOpen, .release = I2C_devRelease,。ioctl = I2C_devIoctl三个结构体变量,这三个用户空间接口驱动函数,完成注册后,用户空间可以采用文件读写的方式来操作I2C设备了,I2C_devOpen函数实现打开字符设备,I2C_devRelease函数实现关闭字符设备,I2C_devIoctl是实现和硬件设备实现数据传输的最重要函数,主要实现设备加载、数据读取和数据写入,从而完成用户空间和驱动程序以及硬件设备的数据交换,具体实现如图3所示。

下面通过I2C_devIoctl介绍这三个函数的实现过程,命令I2C_CMD_SET_DEV_ADDR实现地址设置,I2C_CMD_READ实现数据读取,I2C_CMD_WRITE实现数据写入,最终分别调用,其中I2C_create实现I2C设备加载,I2C_read实现I2C设备数据读取,I2C_write实现I2C设备数据写入,其中I2C_create利用i2c_add_driver调用i2c_probe,最终调用i2c_set_clientdata加载I2C从设备,I2C_read和I2C_write利用i2c_transfer函数调用master_xfer实现数据的读取和写入,具体实现过程如图3所示,其中I2C_devIoctl实现部分代码如下:

int I2C_devIoctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) {

switch(cmd) {

case I2C_CMD_SET_DEV_ADDR://I2C设置地址设置

filp->private_data = I2C_create(arg);

……

case I2C_CMD_READ: //数据读取

status = copy_from_user( (void*)arg, sizeof(transferPrm));

if(status==0) {

status = copy_from_user();//省略参数

if(status==0) {

status = I2C_read();//省略参数

if(status==0) {

status = copy_to_user();//省略参数

}

}

}

break;

case I2C_CMD_WRITE: //数据写入

……

}

return status;



图3 I2C电机驱动设计图

5 I2C应用程序设计

根据I2C驱动程序设计,要正确调用驱动程序,需要实现驱动的用户空间调用函数,主要是实现open和ioctl等调用函数,因此在应用层的接口函数中也需要实现此函数。

i2c_Init()函数实现open函数,调用驱动函数打开该设备驱动,定义一个数据结构体为:

typedef struct {

unsigned char dataSize;

unsigned char count;

unsigned char *reg;

void *value;

} I2C_Data;

该结构体主要用来实现用户空间和内核空间的调用的数据交换,dataSize代表数据的大小,value是传输的数值,reg是传输命令参数,函数有I2c_Read8()是向内核读入一个字节数据,I2c_Write8()是向内核写入一个字节数据,I2c_Read16()是向内核写入2个字节数据,I2c_Write16 ()是向内核写入2个字节数据,下面列举一个函数说明具体的实现过程,

I2c_Write8(int fd unsigned char *reg, unsigned char *value, unsigned char count){

I2C_Data ptr; unsigned int cmd; int status;

ptr.dataSize = 1; ptr.reg = reg; ptr.count = count; ptr.value = value;

cmd = CMD_WRITE;

status = ioctl(fd, cmd, ptr);

if (status != 0)

printf("ioctl I2C_CMD_WRITE error!");

return status;

}

如图4所示,函数最终通过条用ioctl这个函数实现对驱动的调用,其中参数fd是设备句柄,cmd读写控制是命令,其中宏定义I2C_CMD_SET_DEV_ADDR为地址设置命令,I2C_CMD_READ向内核读取数据命令,I2C_CMD_WRITE向内核写入数据命令。

其他3个读写函数实现过程类似,这几个函数是数据写入读出的函数接口,方便应用层实现调用。



图4云台电机控制应用程序设计图

6云台电机控制应用程序设计

云台很重要部分是电机转动控制,本课题研究采用图像界面实现人机交互,其中界面设计采用QT图形界面软件来设计,可以在界面操作实现电机的水平转动、垂直转动,逆时针转动和顺时针转动,从而带动视频监控的摄像头朝不同方位转动以及定位,如图所示。根据协议,应用程序设计主要实现以下操作:

(1)获取当前的垂直位置,函数接口为get_motor_curVertical_ptr (),返回垂直位置值;

(2)获取当前的水平位置,函数接口为get_motor_curHorizontal_ptr (),返回水平位置值;

(3)设置垂直运行的停止位置,函数接口为set_motor_vertical_ptr (unsigned short ptr),参数ptr为设置的垂直停止位置值;

(4)设置水平运行的停止位置,函数接口为set_motor_horizontal_ptr (unsigned short ptr)参数ptr为设置的水平停止位置值;

(5)水平操作和垂直操作的启动操作,接口函数为set_motor_opt(bool bVertical, bool bHorizontal),参数bVertical表示是否启动垂直操作,bHorizontal表示是否启动水平操作

(6)设置运行速度,函数接口为set_motor_speed(unsigned char vertical_speed, unsigned char horizontal_speed),参数vertical_speed控制垂直方向速度值,horizontal_speed控制水平方向速度值;

(7)设置电机运行方向,接口函数set_motor_direction(bool bVertical, bool bHorizontal),设置运行方向为顺时针或者逆时针,参数bVertical为真表示垂直方向向上运动,为假表示向下运动;bHorizontal为真,表示水平方向逆时针,否则为顺时针。

下面通过运动速度的接口函数set_motor_speed(),详细介绍云台控制接口函数的实现过程,电机转动速度设置函数设置set_motor_speed(),其中函数参数vertical_speed为垂直方向运动速度;horizontal_speed为水平方向运动速度,局部变量reg用于制定控制类型,value设计为16位,其中高8位存放垂直转动速度数值命令,低8为存放水平转动速度数值,参数设置完后调用I2c_Write16()函数,从而调用ioctl实现对驱动的调用,最终通过I2C总线控制电机,达到电机快速转动、定位准确。

set_motor_speed(unsigned char vertical_speed, unsigned char horizontal_speed) {

int ret;

unsigned char reg;

unsigned short value=0;

reg = 3;

value = vertical_speed

value |= horizontal_speed;

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top