ARM Linux控制CDS5516

来源:互联网 发布:amarra 4 for mac 编辑:程序博客网 时间:2024/06/06 20:31

蛋疼了这么久..最后竟然不用了,好忧伤....


/* * ServoCDS55XX.h * *  Created on: Sep 28, 2013 *      Author: wgh */#ifndef SERVOCDS55XX_H#define SERVOCDS55XX_H#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <termios.h>#include <string.h>#include <stdarg.h>#include <sys/ioctl.h>#include <sys/cdefs.h>typedef unsigned char uchar;typedef unsigned int uint;#define CFG_PRINT_WRITE#define CFG_PRINT_FUNC/* * 下边所有函数中的使用的buf参数都需要在外部定义,参考具体指令的长度,buf的长度要取可能 * 用到的最长指令的长度,所有函数中的ms请按具体时间定义,(write_port中默认有1s延时...) */void sleep(int ms);int open_port(const char *name);int write_port(int fd, const uchar *data, int len);int read_port(int fd, const uchar *data, int len);//int write_servo(int fd, const uchar *data, int len);//int read_servo(int fd, const uchar *data, int len);int parse_servo_msg(const uchar *data, int len);int cfg_port(int fd, int nSpeed, int nBits, char nEvent, int nStop);int read_servo_ct(int fd, uchar *buf, int ms, uchar id,  uchar addr, uchar len);int read_servo_baudrate(int fd, uchar *buf, int ms, uchar id);int read_servo_temperature(int fd, uchar *buf, int ms, uchar id);int read_servo_position(int fd, uchar *buf, int ms, uchar id);int write_servo_op(int fd, uchar *buf, int ms, uchar id, uchar op, uchar len, ...);int write_servo_ct(int fd, uchar *buf, int ms, uchar id, uchar addr, uchar len, ...);int write_servo_reg(int fd, uchar *buf, int ms, uchar id, uchar addr, uchar len, ...);int write_servo_sync(int fd, uchar *buf, int ms, uchar servoCnt, uchar addr, uchar len, ...);int action_servo(int fd, uchar *buf, int ms, uchar id);int reset_servo(int fd, uchar *buf, int ms, uchar id);int ping_servo(int fd, uchar *buf, int ms, uchar id);int set_servo_id(int fd, uchar *buf, int ms, uchar id);int set_servo_clockwise_limit(int fd, uchar *buf, int ms, uchar id, uchar cll, uchar clh);int set_servo_anticlockwise_limit(int fd, uchar *buf, int ms, uchar id, uchar all, uchar alh);int set_servo_degree_limit(int fd, uchar *buf, int ms, uchar id, uint cdl, uint adl);int set_servo_position(int fd, uchar *buf, int ms, uchar id, uint pos, uint vel);int set_servo_motorMode(int fd, uchar *buf, int ms, uchar id);int set_servo_speed(int fd, uchar *buf, int ms, uchar id, uint speed);#endif


/* * ServoCDS55XX.cpp * *  Created on: Sep 28, 2013 *      Author: wgh */#include "ServoCDS55XX.h"#ifdef CFG_PRINT_FUNC#define PRINT_FUNC_MSG(id, ms)\printf("%s : id(%d) delay(%d)....\n", __func__, id, ms)#else#define PRINT_FUNC_MSG#endifvoid sleep(int ms){    //struct timespec ts = {    //ms/1000, (ms%1000)*1000*1000 };    //nanosleep(&ts, NULL);    usleep(1000*ms);}int open_port(const char *name){    int fd;    printf("open device: %s\n", name);    fd = open(name, O_RDWR /*| O_NOCTTY | O_NDELAY*/);    if(fd < 0){        printf("can't open %s!!!\n", name);        exit(1);    }else{        //fcntl(fd, F_SETFL, 0);    }    return fd;}int read_port(int fd, const uchar *data, int len){    return read(fd, (void*)data, len);}int write_port_one_byte(int fd, uchar data){uchar buff[1];buff[0] = data;return write(fd, buff, 1);//sleep(500);}int write_port(int fd, const uchar *data, int len){#ifdef CFG_PRINT_WRITEint sum = 0;printf("write(%d): ", len);for(int i=0; i<len; i++){printf("%2x, ", data[i]);sum += write_port_one_byte(fd, data[i]);}printf(".......%d\n", sum);#endif//    write(fd, data, len);    sleep(1000);    return sum;}/* * cfg_port : 配置串口设置,目前只支持115200,1000000 */int cfg_port(int fd, int nSpeed, int nBits, char nEvent, int nStop){printf("cfg_port : fd(%d), nSpeed(%d), nBits(%d), nEvent(%c), nStop(%d)..\n",fd, nSpeed, nBits, nEvent, nStop);    struct termios newOpt, oldOpt;    if(0 != tcgetattr(fd, &oldOpt)){/* get the current options for the port */        perror("tcgetttr error...\n");        exit(1);    }    bzero(&newOpt, sizeof(newOpt));    newOpt.c_cflag |= CLOCAL | CREAD;/* enable the receiver and set local mode */    newOpt.c_cflag &= ~CSIZE;/* mask the character size bits */    switch(nBits){        case 7:            newOpt.c_cflag |= CS7;            break;        case 8:            newOpt.c_cflag |= CS8;/* select 8 data bits */            break;        default:            perror("bad nBits!...\n");            exit(1);    }    switch(nEvent){        case 'O':/* odd */            newOpt.c_cflag |= PARENB;            newOpt.c_cflag |= PARODD;            newOpt.c_iflag |= (INPCK | ISTRIP);            break;        case 'E':            newOpt.c_cflag |= PARENB;            newOpt.c_cflag &= ~PARODD;            newOpt.c_iflag |= (INPCK | ISTRIP);            break;        case 'N':            newOpt.c_cflag &= ~PARENB;//            newOpt.c_cflag &= ~INPCK;/* enable parity checking */            break;        default:            perror("bad nEvent!...\n");            exit(1);    }    switch(nSpeed){case 115200:cfsetispeed(&newOpt, B115200);cfsetospeed(&newOpt, B115200);break;case 1000000:cfsetispeed(&newOpt, B1000000);cfsetospeed(&newOpt, B1000000);break;default:perror("bad baudrate...\n");exit(1);    }    if(nStop == 1){        newOpt.c_cflag &= ~CSTOPB;    }else{        newOpt.c_cflag |= CSTOPB;    }    ////newOpt.c_cflag &= CNEW_RTSCTS;/* disable hardware flow control */    //newOpt.c_iflag &= ~(IXON | IXOFF | IXANY);/* disable software flow control *///    newOpt.c_oflag &= ~OPOST;  /* choosing raw output *///    newOpt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);/* choosing raw input */    newOpt.c_cc[VTIME] = 150;    newOpt.c_cc[VMIN] = 0;    tcflush(fd, TCIFLUSH);    if(0 != tcsetattr(fd, TCSANOW, &newOpt)){/* set the new options for the port */                                    /* other arguments : TCSADRAIN TCSAFLUSH */        perror("tcsetattr error!...\n");        exit(1);    }    printf("cfg port ok!...\n");    return 0;}//int read_servo(int fd, const uchar *data, int len)//{//    int ret = read_port(fd, data, len);//    sleep(100);//    return ret;//}////int write_servo(int fd, const uchar *data, int len)//{//    int ret = write_port(fd, data, len);//    sleep(500);//    return ret;//}/* * parse_servo_msg : */int parse_servo_msg(const uchar *data, int len){    for(int i=0; i<len; i++)        printf(" %2x,", data[i]);    printf("\n");    return 0;}int set_servo_id(int fd, uchar *buf, int ms, uchar id){PRINT_FUNC_MSG(id, ms);return write_servo_ct(fd, buf, ms, 0xfe, 0x03, 0x01, id);}/* * read_servo_ct:读舵机内存控制表 */int read_servo_ct(int fd, uchar *buf, int ms, uchar id, uchar addr, uchar len){PRINT_FUNC_MSG(id, ms);return write_servo_op(fd, buf, ms, id, 0x02, 0x02, addr, len);}int read_servo_baudrate(int fd, uchar *buf, int ms, uchar id){PRINT_FUNC_MSG(id, ms);return read_servo_ct(fd, buf, ms, id, 0x04, 0x01);}int read_servo_temperature(int fd, uchar *buf, int ms, uchar id){PRINT_FUNC_MSG(id, ms);return read_servo_ct(fd, buf, ms, id, 0x2b, 0x01);}int read_servo_position(int fd, uchar *buf, int ms, uchar id){PRINT_FUNC_MSG(id, ms);return read_servo_ct(fd, buf, ms, id, 0x24, 0x02);}int write_servo_op(int fd, uchar *buf, int ms, uchar id, uchar op, uchar len, ...){PRINT_FUNC_MSG(id, ms);int ret = 0;buf[0] = 0xff;buf[1] = 0xff;buf[2] = id;buf[3] = len+2;buf[4] = op;int i;va_list vl;va_start(vl, len);for(i=0; i<len; i++){buf[5+i] = (uchar)va_arg(vl, int);}va_end(vl);buf[5+len] = 0;for(int j=2; j<5+len; j++)buf[5+len] += buf[j];buf[5+len] = ~buf[5+len];ret = write_port(fd, buf, 6+len);sleep(ms);return ret;}/* * 写舵机内存控制表 */int write_servo_ct(int fd, uchar *buf, int ms, uchar id, uchar addr, uchar len, ...){//ret = write_servo_op(fd, buf, ms, id, 0x03, len+1, addr, vl);PRINT_FUNC_MSG(id, ms);int ret = 0;buf[0] = 0xff;buf[1] = 0xff;buf[2] = id;buf[3] = len+3;buf[4] = 0x03;buf[5] = addr;int i;va_list vl;va_start(vl, len);for(i=0; i<len; i++){buf[6+i] = (uchar)va_arg(vl, int);}va_end(vl);buf[6+len] = 0;for(int j=2; j<6+len; j++)buf[6+len] += buf[j];buf[6+len] = ~buf[6+len];ret = write_port(fd, buf, 7+len);sleep(ms);return ret;}int write_servo_reg(int fd, uchar *buf, int ms, uchar id, uchar addr, uchar len, ...){PRINT_FUNC_MSG(id, ms);int ret = 0;buf[0] = 0xff;buf[1] = 0xff;buf[2] = id;buf[3] = len+3;buf[4] = 0x04;buf[5] = addr;int i;va_list vl;va_start(vl, len);for(i=0; i<len; i++){buf[6+i] = (uchar)va_arg(vl, int);}va_end(vl);buf[6+len] = 0;for(int j=2; j<6+len; j++)buf[6+len] += buf[j];buf[6+len] = ~buf[6+len];ret = write_port(fd, buf, 7+len);sleep(ms);return ret;}/* * 同步写指令 */int write_servo_sync(int fd, uchar *buf, int ms, uchar cnt, uchar addr, uchar len, ...){PRINT_FUNC_MSG(0xfe, ms);int ret = 0;buf[0] = 0xff;buf[1] = 0xff;buf[2] = 0xfe;buf[3] = (len+1)*cnt+4;buf[4] = 0x83;buf[5] = addr;buf[6] = len;int i;va_list vl;va_start(vl, len);for(i=0; i<(len+1)*cnt; i++){buf[7+i] = (uchar)va_arg(vl, int);}va_end(vl);buf[7+(len+1)*cnt] = 0;for(int j=2; j<7+(len+1)*cnt; j++)buf[7+(len+1)*cnt] += buf[j];buf[7+(len+1)*cnt] = ~buf[7+(len+1)*cnt];ret = write_port(fd, buf, 8+(len+1)*cnt);sleep(ms);return ret;}int action_servo(int fd, uchar *buf, int ms, uchar id){PRINT_FUNC_MSG(id, ms);return write_servo_op(fd, buf, ms, id, 0x05, 0x00);}/* * reset_servo将初始化舵机的波特率为1M,不要使用 */int reset_servo(int fd, uchar *buf, int ms, uchar id){PRINT_FUNC_MSG(id, ms);printf("warning : reset servo(%d)...!!!!!\n", id);return write_servo_op(fd, buf, ms, id, 0x06, 0x00);}/* * 查询舵机当前状态 */int ping_servo(int fd, uchar *buf, int ms, uchar id){PRINT_FUNC_MSG(id, ms);return write_servo_op(fd, buf, ms, id, 0x01, 0x00);}int set_servo_clockwise_limit(int fd, uchar *buf, int ms, uchar id, uchar cll, uchar clh){PRINT_FUNC_MSG(id, ms);    return write_servo_ct(fd, buf, ms, id, 0x06, 0x02, cll, clh);}int set_servo_anticlockwise_limit(int fd, uchar *buf, int ms, uchar id, uchar all, uchar alh){PRINT_FUNC_MSG(id, ms);    return write_servo_ct(fd, buf, ms, id, 0x08, 0x02, all, alh);}int set_servo_degree_limit(int fd, uchar *buf, int ms, uchar id, uint cdl, uint adl){PRINT_FUNC_MSG(id, ms);    return write_servo_ct(fd, buf, ms, id, 0x06, 0x04,    (uchar)(cdl), (uchar)(cdl>>8), (uchar)(adl), (uchar)(adl>>8));}int set_servo_position(int fd, uchar *buf, int ms, uchar id, uint pos, uint vel){PRINT_FUNC_MSG(id, ms);    return write_servo_ct(fd, buf, ms, id, 0x1e, 0x04,    (uchar)(pos), (uchar)(pos>>8), (uchar)(vel), (uchar)(vel>>8));}int set_servo_motorMode(int fd, uchar *buf, int ms, uchar id){PRINT_FUNC_MSG(id, ms);return set_servo_degree_limit(fd, buf, ms, id, 0x00, 0x00);}int set_servo_speed(int fd, uchar *buf, int ms, uchar id, uint speed){PRINT_FUNC_MSG(id, ms);return write_servo_ct(fd, buf, ms, id, 0x20, 0x02, (uchar)(speed), (uchar)(speed>>8));}

#include <iostream>#include "ServoCDS55XX.h"using namespace std;#define DEFAULT_PORT "/dev/ttySAC1"#define DEFAULT_ID      254#define DEFAULT_DELAY 0#define TEST(str, func) \printf("...test %s..\n", str);\cnt = 3;\do{\func;\if((len = read_port(fd, buf2, 1024))){\printf("(%d)read(%d): ", cnt, len);\parse_servo_msg(buf2, len);\}\cnt--;\}while(cnt && len<=11)int main(int argc, char **argv){    int i, len, cnt;    int fd;    uchar id;    uchar buf[1024], buf2[1024];    int pos;    memset(buf2, 0, sizeof(buf2));    if(argc == 3){        fd = open_port(argv[1]);        id = (uchar)atoi(argv[2]);    }else if(argc == 2){        fd = open_port(DEFAULT_PORT);        id = (uchar)atoi(argv[1]);    }    printf("servo id = %d\n", id);    cfg_port(fd, 115200, 8, 'N', 1);//    cfg_port(fd, 1000000, 8, 'N', 1);    TEST("degree", set_servo_degree_limit(fd, buf, 2500, id, 0x00, 0x3ff));//    TEST("pos", set_servo_position(fd, buf, 2500, id, 0x01ff, 0x0200));//    sleep(10000);//    TEST("set motor mode", set_servo_motorMode(fd, buf, 2500, id));//    TEST("set motor speed", set_servo_speed(fd, buf, 2500, id, 0x2ff));//    sleep(10000);    for(int i=0; i<10; i++){    printf("-----------%d-----------\n", i);    TEST("pos", set_servo_position(fd, buf, 2500, id, 0x02ff, 0x0200));    TEST("pos", set_servo_position(fd, buf, 2500, id, 0x0000, 0x0200));    }//    TEST("set motor speed", set_servo_speed(fd, buf, 1000, id, 0x00));    close(fd);    return 0;}