解析MWC的串口通讯正式版20130407.doc_第1页
解析MWC的串口通讯正式版20130407.doc_第2页
解析MWC的串口通讯正式版20130407.doc_第3页
解析MWC的串口通讯正式版20130407.doc_第4页
解析MWC的串口通讯正式版20130407.doc_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

解析MWC的串口通讯一使用的软件 二使用的MWC定义串口协议文件updated 04 JulyMultiwii serial protocol was redesigned: to be light, as before to be generic: it can be used transparenlty by a GUI, OSD, telemetry or home made config tool.ie no more specific OSD code should be coded in multiwii to be bit wire efficient: only requested data are transmitted in a binary format to be quite secure: data are sent with a checksum, preventing corrupted configuration to be injected. to be header sensitive: as it is designed with a specific header, it can be mixed with other frame, like GPS frameie, it will be possible to connect either a GUI or a GPS on the same serial port without changing the conf to be less sensitive to evolutions:ie in case of parameter evolution, the main protocol will remain compatible and the GUI will be much less version dependent.variable data length allows to consider only the beginning of a message, leaving the other octets at the end to extend transparently the message (for instance to add a new PID)I thought first about an implementation of Mavlink, but I think its not what I was looking for.Even with a partial implementation, the predefined structures are not light enough for what I have in mind.Some messages are however inspired from mavlink structure.The main rule remains: Multiwii never sends something on its own.A request must be done in each case to retrieve or set data.Each messages received are acknowledged even if there is no data inside.There are 2 main messages to consider:request message to multiwiimultiwii output messagerequest message to multiwiiTo request simple data without parameters / send a specific command / inject new parameters in multiwiimessages are formated like this:$Mdata lengthcodedatachecksum1 octet $1 octet M1 octet data lengthcodedatachecksum1 octet $1 octet M1 octet 1 octet data length1 octet codeseveral octets data1 octet checksumif the message is unknown:$M|0codechecksum1 octet $1 octet M1 octet |1 octet 01 octet unknown code1 octet checksum三、对写入MWC的原文件分析void serialCom() / MWC通过c = SerialRead(CURRENTPORT);解析缓冲区的数据 uint8_t c,n; static uint8_t offsetUART_NUMBER; static uint8_t dataSizeUART_NUMBER; static enum _serial_state /串口的几种状态 IDLE, /空闲? HEADER_START, /数据头 开始 $ HEADER_M, /数据头 M HEADER_ARROW, /数据 箭头 HEADER_SIZE, /数据尺寸 HEADER_CMD, /指令 c_stateUART_NUMBER;/ = IDLE;/状态数组 默认 空闲 for(n=0;n 1) #define SPEK_COND & (SPEK_SERIAL_PORT != CURRENTPORT) #endif while (SerialAvailable(CURRENTPORT) GPS_COND SPEK_COND) /while循环 uint8_t bytesTXBuff = (uint8_t)(serialHeadTXCURRENTPORT-serialTailTXCURRENTPORT)%TX_BUFFER_SIZE; / indicates the number of occupied bytes in TX buffer 发送缓冲区占用字节标定。 if (bytesTXBuff TX_BUFFER_SIZE - 50 ) return; / ensure there is enough free TX buffer to go further (50 bytes margin) 确保发送缓冲区之手50字节的余量。 c = SerialRead(CURRENTPORT); /读串口缓冲区serialBufferRX数据指针串口端口号,该缓冲区的数据是由串口接收中断函数inline store_uart_in_buf(uint8_t data, uint8_t portnum)获取的来自电脑的数据。 if (c_stateCURRENTPORT = IDLE) /这是一组完整指令代码 24 4D 3C 00 64 64 $M#0dd /串口状态空闲 等待HEADER_START状态的到来。 c_stateCURRENTPORT = (c=$) ? HEADER_START : IDLE;/判定是$字符吗?是进入HEADER_START状态。 if (c_stateCURRENTPORT = IDLE) evaluateOtherData(c); / evaluate all other incoming serial data else if (c_stateCURRENTPORT = HEADER_START) c_stateCURRENTPORT = (c=M) ? HEADER_M : IDLE; else if (c_stateCURRENTPORT = HEADER_M) c_stateCURRENTPORT = (c=) ? HEADER_ARROW : IDLE;/是字符 INBUF_SIZE) / now we are expecting the payload size 我们期望足够的数据占用缓冲区。 c_stateCURRENTPORT = IDLE;/数据位置不够 退出循环。 continue; /不执行该while循环包含的后面的语句,跳出开始下一轮循环。 dataSizeCURRENTPORT = c;/缓冲区够,将收到的数据赋值给当前端口的数据尺寸数组dataSize串口端口号。 offsetCURRENTPORT = 0;/设置数据指针的偏移位0。 checksumCURRENTPORT = 0;/初始化数据的校验和为0。存入数组中。 indRXCURRENTPORT = 0;/ checksumCURRENTPORT = c;/说明数据长度是校验的第一个字母。 c_stateCURRENTPORT = HEADER_SIZE; / the command is to follow/MWC收到数据长度,后面就是电脑发送的数据了。MWC串口状态进入HWADER_SIZE。 else if (c_stateCURRENTPORT = HEADER_SIZE) /MWC串口是在HEADER_SIZE状态吗? cmdMSPCURRENTPORT = c;/在HEADER_SIZE状态收到的第一个数据是指令。 checksumCURRENTPORT = c;/将该数据异或进入校验和的数组中去。 c_stateCURRENTPORT = HEADER_CMD;/MWC收到数据后,说明在指令状态,MWC进入HEAFER_CMD状态。 else if (c_stateCURRENTPORT = HEADER_CMD & offsetCURRENTPORT = dataSizeCURRENTPORT) /判定偏移指针大于等于数据预留位置大小吗? if (checksumCURRENTPORT = c) / compare calculated and transferred checksum /偏移指针大于等于数据预留位置大小,就将从电脑这次收到的数据作为校验和,与已经累计异或的checksum中的校验和数据对比,为真,表示,该数据包是有效的,可以调用下面的函数evaluateCommand()进行,数据包的解析。 evaluateCommand(); / we got a valid packet, evaluate it我们获得了一个有效的数据包,解析评估这些数据。 c_stateCURRENTPORT = IDLE;/MWC串口开始进入空闲状态。 /while循环 /for循环四、对MWC的配置文件的原文件分析 if (time-time2)40 & ! toggleRead & ! toggleWrite) /不按读写按钮发送的78个数据 time2=time; int requests = MSP_IDENT, MSP_MOTOR_PINS, MSP_STATUS, MSP_RAW_IMU, MSP_SERVO, MSP_MOTOR, MSP_RC, MSP_RAW_GPS, MSP_COMP_GPS, MSP_ALTITUDE, MSP_BAT, MSP_DEBUGMSG, MSP_DEBUG;/100=d 115=s 102=f 103=g 104=h 105=I 106=j 107=k 109=m 110=n 253 254 sendRequestMSP(requestMSP(requests); if (time-time3)20 & ! toggleRead & ! toggleWrite) sendRequestMSP(requestMSP(MSP_ATTITUDE);/108=l time3=time; if (toggleReset) toggleReset=false; toggleRead=true; sendRequestMSP(requestMSP(MSP_RESET_CONF);/MSP_RESET_COF=208 if (toggleRead) /只要按读按钮 就发送下面的代码36个 toggleRead=false; int requests = MSP_BOXNAMES, MSP_PIDNAMES, MSP_RC_TUNING, MSP_PID, MSP_BOX, MSP_MISC ;/116=t 117=u 111=o 112=p 113=q 114=r sendRequestMSP(requestMSP(requests); buttonWRITE.setColorBackground(green_); if (toggleCalibAcc) toggleCalibAcc=false; sendRequestMSP(requestMSP(MSP_ACC_CALIBRATION); if (toggleCalibMag) toggleCalibMag=false; sendRequestMSP(requestMSP(MSP_MAG_CALIBRATION); if (toggleWrite) toggleWrite=false; / MSP_SET_RC_TUNING payload = new ArrayList(); payload.add(char( round(confRC_RATE.value()*100) ); payload.add(char( round(confRC_EXPO.value()*100) ); payload.add(char( round(rollPitchRate.value()*100) ); payload.add(char( round(yawRate.value()*100) ); payload.add(char( round(dynamic_THR_PID.value()*100) ); payload.add(char( round(throttle_MID.value()*100) ); payload.add(char( round(throttle_EXPO.value()*100) ); sendRequestMSP(requestMSP(MSP_SET_RC_TUNING,payload.toArray( new Characterpayload.size() ); / MSP_SET_PID payload = new ArrayList(); for(i=0;iPIDITEMS;i+) bytePi = (round(confPi.value()*10); byteIi = (round(confIi.value()*1000); byteDi = (round(confDi.value(); .五、MWC处理指令的代码分析 void evaluateCommand() switch(cmdMSPCURRENTPORT) case MSP_SET_RAW_RC: for(uint8_t i=0;i8;i+) rcDatai = read16(); headSerialReply(0); break; #if GPS case MSP_SET_RAW_GPS: f.GPS_FIX = read8(); GPS_numSat = read8(); GPS_coordLAT = read32(); GPS_coordLON = read32(); GPS_altitude = read16(); GPS_speed = read16(); GPS_update |= 2; / New data signalisation to GPS functions headSerialReply(0); break; #endif case MSP_SET_PID: for(uint8_t i=0;i#0#0MSP_SET_PID” break; case MSP_SET_BOX: for(uint8_t i=0;iCHECKBOXITEMS;i+) conf.activatei=read16(); headSerialReply(0); break; case MSP_SET_RC_TUNING: conf.rcRate8 = read8(); conf.rcExpo8 = read8(); conf.rollPitchRate = read8(); conf.yawRate = read8(); conf.dynThrPID = read8(); conf.thrMid8 = read8(); conf.thrExpo8 = read8(); headSerialReply(0); break; case MSP_SET_MISC: #if defined(POWERMETER) conf.powerTrigger1 = read16() / PLEVELSCALE; #endif headSerialReply(0); break; case MSP_IDENT: headSerialReply(7); serialize8(VERSION); / multiwii version serialize8(MULTITYPE); / type of multicopter serialize8(MSP_VERSION); / MultiWii Serial Protocol Version serialize32(0); / capability break; case MSP_STATUS: headSerialReply(10); serialize16(cycleTime); serialize16(i2c_errors_count); serialize16(ACC|BARO1|MAG2|GPS3|SONAR4); serialize32( #if ACC f.ANGLE_MODEBOXANGLE| f.HORIZON_MODEBOXHORIZON| #endif #if BARO & (!defined(SUPPRESS_BARO_ALTHOLD) f.BARO_MODEBOXBARO| #endif #if MAG f.MAG_MODEBOXMAG|f.HEADFREE_MODEBOXHEADFREE|rcOptionsBOXHEADADJBOXHEADADJ| #endif #if defined(SERVO_TILT) | defined(GIMBAL) rcOptionsBOXCAMSTABBOXCAMSTAB| #endif #if defined(CAMTRIG) rcOptionsBOXCAMTRIGBOXCAMTRIG| #endif #if GPS f.GPS_HOME_MODEBOXGPSHOME|f.GPS_HOLD_MODEBOXGPSHOLD| #endif #if defined(FIXEDWING) | defined(HELICOPTER) | defined(INFLIGHT_ACC_CALIBRATION) f.PASSTHRU_MODEBOXPASSTHRU| #endif #if defined(BUZZER) rcOptionsBOXBEEPERONBOXBEEPERON| #endif #if defined(LED_FLASHER) rcOptionsBOXLEDMAXBOXLEDMAX| #endif #if defined(LANDING_LIGHTS_DDR) rcOptionsBOXLLIGHTSBOXLLIGHTS | #endif f.ARMEDBOXARM); break; case MSP_RAW_IMU: headSerialReply(18); for(uint8_t i=0;i3;i+) serialize16(accSmoothi); for(uint8_t i=0;i3;i+) serialize16(gyroDatai); for(uint8_t i=0;i3;i+) serialize16(magADCi); break; case MSP_SERVO: headSerialReply(16);/发送数据头 包括数据长度 指令码 初始化校验和 for(uint8_t i=0;i8;i+) #if defined(SERVO) serialize16(servoi); #else serialize16(0); #endif break; case MSP_MOTOR: headSerialReply(16); for(uint8_t i=0;i8;i+) serialize16( (i NUMBER_MOTOR) ? motori : 0 ); break; case MSP_RC: headSerialReply(16); for(uint8_t i=0;i8;i+) serialize16(rcDatai); break; #if GPS case MSP_RAW_GPS: headSerialReply(14); serialize8(f.GPS_FIX); serialize8(GPS_numSat); serialize32(GPS_coordLAT); serialize32(GPS_coordLON); serialize16(GPS_altitude); serialize16(GPS_speed); break; case MSP_COMP_GPS: headSerialReply(5); serialize16(GPS_distanceToHome); serialize16(GPS_directionToHome); serialize8(GPS_update & 1); break; #endif case MSP_ATTITUDE: headSerialReply(8); for(uint8_t i=0;i2;i+) serialize16(anglei); serialize16(heading); serialize16(headFreeModeHold); break; case MSP_ALTITUDE: headSerialReply(4); serialize32(EstAlt); break; case MSP_BAT: headSerialReply(3); serialize8(vbat); serialize16(intPowerMeterSum); break; case MSP_RC_TUNING: headSerialReply(7); serialize8(conf.rcRate8); serialize8(conf.rcExpo8); serialize8(conf.rollPitchRate); serialize8(conf.yawRate); serialize8(conf.dynThrPID); serialize8(conf.thrMid8); serialize8(conf.thrExpo8); break; case MSP_PID: headSerialReply(3*PIDITEMS); for(uint8_t i=0;iPIDITEMS;i+) serialize8(conf.P8i); serialize8(conf.I8i); serialize8(conf.D8i); break; case MSP_BOX: headSerialReply(2*CHECKBOXITEMS); for(uint8_t i=0;iCHECKBOXITEMS;i+) serialize16(conf.activatei); break; case MSP_BOXNAMES: headSerialReply(strlen_P(boxnames); serializeNames(boxnames); break; case MSP_PIDNAMES: headSerialReply(strlen_P(pidnames); serializeNames(pidnames); break; case MSP_MISC: headSerialReply(2); serialize16(intPowerTrigger1); break; case MSP_MOTOR_PINS: headSerialReply(8); for(uint8_t i=0;i8;i+) serialize8(PWM_PINi); break; #if defined(USE_MSP_WP) case MSP_WP: uint8_t wp_no = read8(); /get the wp number headSerialReply(12); if (wp_no = 0) serialize8(0); /wp0 serialize32(GPS_homeLAT); serialize32(GPS_homeLON); serialize16(0); /altitude will come here serialize8(0); /nav flag will come here else if (wp_no = 16) serialize8(16); /wp16 serialize32(GPS_holdLAT); serialize32(GPS_holdLON); serialize16(0); /altitude will come here serialize8(0); /nav flag will come here break; #endif case MSP_RESET_CONF: if(!f.ARMED) conf.checkNewConf+; checkFirstTime(); headSerialReply(0); break; case MSP_ACC_CALIBRATION: if(!f.ARMED) calibratingA=400; headSerialReply(0); break; case MSP_MAG_CALIBRATION: if(!f.ARMED) f.CALIBRATE_MAG = 1; headSerialReply(0); break; case MSP_EEPROM_WRITE: writeParams(0); headSerialReply(0); break; case MSP_DEBUG: headSerialReply(8); for(uint8_t i=0;i 16) size = 16; headSerialReply(size); debugmsg_serialize(size); break; #endif default: / we do not know how to handle the (valid) message, indicate error MSP $M! headSerialError(0); break; tailSerialReply();/上面case执行完成后,发送最后一个数据 实际就是发送校验和。二、测试过程1、打开32位MWC配置软件 选择串行口 按erad读取数据2、打开串口监视精灵 特别是115200波特率的选择十分重要,因为MWC的软件就是这样写的,设定的。监视到的原始数据COM3,Wirte(36): $M#0tt$M#0uu$M#0oo$M#0pp$M#0qq$MCOM3, Read(1): ,COM3, Read(1): tCOM3, Read(1): ACOM3, Read(1): NCOM3, Read(1): GCOM3, Read(1): LCOM3, Read(1): M.COM3, Read(1): #0COM3, Read(1): #0COM3, Read(1): #0COM3, Read(1): #0COM3, Read(1): COM3, Read(1): $COM3, Read(1): MCOM3, Read(1): COM3, Read(1): #2COM3, Read(1): rCOM3, Read(1): #0COM3, Read(1): #0COM3, Read(1): pCOM3,Wirte(78): $M#0dd$M#0ss$M#0ee$M#0ff$M#0gg$M#0hh$M#0ii$M#0jj$M#0kk$M#0mm$M#0nn$M#0$M#0COM3,Wirte(6): $MCOM3, Read(1): #7COM3, Read(1): dCOM3, Read(1): COM3, Read(1): #2COM3, Read(1): #0COM3, Read(1): #0COM3, Read(1): #0COM3, Read(1): #0COM3, Read(1): #0COM3, Read(1): COM3, Read(1): $COM3, Read(1): MCOM3, Read(1): COM3, Read(1): #8COM3, Read(1): sCOM3, Read(1): #9COM3, Read(1): #10COM3, Read(1): #11COM3, Read(1): #3COM3, Read(1): #6COM3, Read(1): #5COM3, Read(1): #16COM3, Read(1): #12COM3, Read(1): oCOM3, Read(1): $COM3, Read(1): MCOM3, Read(1): COM3, Read(1): #10COM3, Read(1): eCOM3, Read(1): COM3, Read(1): #11COM3, Read(1): #0COM3, Read(1): #0COM3, Read(1): #7COM3, Read(1

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论