zoukankan      html  css  js  c++  java
  • mpu6050

    今天有点时间,来说说MPU6050吧,MPU-6050为全球首例整合性6轴运动处理组件,整合了3轴陀螺仪、3轴加速器,并含可藉由第二个I2C端口连接其他厂牌之加速器、磁力传感器、或其他传感器的数位运动处理(DMP: Digital Motion Processor)硬件加速引擎,由主要I2C端口以单一数据流的形式,向应用端输出完整的9轴融合演算技术InvenSense的运动处理资料库,可处理运动感测的复杂数据,降低了运动处理运算对操作系统的负荷,并为应用开发提供架构化的API。其与MCU通信是通过I2C,今天是用STM32F401进行读取MPU6050的数据,MPU6050模块的电源我是用的3.3V,另外SCL和SDA两个脚分别接一个3.3K或2K的上拉电阻,先写好底层驱动I2C(由于STM32的硬件I2C不太稳定,此次用的是软件仿真I2C)

    #include "i2c.h" #define  I2C_Direction_Transmitter      ((uint8_t)0x00) #define  I2C_Direction_Receiver         ((uint8_t)0x01)

    #define SCL_H         GPIOB->BSRRL = GPIO_Pin_6 /* GPIO_SetBits(GPIOB , GPIO_Pin_6)   */ #define SCL_L         GPIOB->BSRRH  = GPIO_Pin_6 /* GPIO_ResetBits(GPIOB , GPIO_Pin_6) */

    #define SDA_H         GPIOB->BSRRL = GPIO_Pin_7 /* GPIO_SetBits(GPIOB , GPIO_Pin_7)   */ #define SDA_L         GPIOB->BSRRH  = GPIO_Pin_7 /* GPIO_ResetBits(GPIOB , GPIO_Pin_7) */

    #define SCL_read      GPIOB->IDR  & GPIO_Pin_6 /* GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_6) */ #define SDA_read      GPIOB->IDR  & GPIO_Pin_7 /* GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_7) */

    static void I2C_delay(void) {     volatile int i = 7;     while (i)         i--; }

    static bool I2C_Start(void) {     SDA_H;     SCL_H;     I2C_delay();     if (!SDA_read)         return false;     SDA_L;     I2C_delay();     if (SDA_read)         return false;     SDA_L;     I2C_delay();     return true; }

    static void I2C_Stop(void) {     SCL_L;     I2C_delay();     SDA_L;     I2C_delay();     SCL_H;     I2C_delay();     SDA_H;     I2C_delay(); }

    static void I2C_Ack(void) {     SCL_L;     I2C_delay();     SDA_L;     I2C_delay();     SCL_H;     I2C_delay();     SCL_L;     I2C_delay(); }

    static void I2C_NoAck(void) {     SCL_L;     I2C_delay();     SDA_H;     I2C_delay();     SCL_H;     I2C_delay();     SCL_L;     I2C_delay(); }

    static bool I2C_WaitAck(void) {     SCL_L;     I2C_delay();     SDA_H;     I2C_delay();     SCL_H;     I2C_delay();     if (SDA_read) {         SCL_L;         return false;     }     SCL_L;     return true; }

    static void I2C_SendByte(uint8_t byte) {     uint8_t i = 8;     while (i--) {         SCL_L;         I2C_delay();         if (byte & 0x80)             SDA_H;         else             SDA_L;         byte <<= 1;         I2C_delay();         SCL_H;         I2C_delay();     }     SCL_L; }

    static uint8_t I2C_ReceiveByte(void) {     uint8_t i = 8;     uint8_t byte = 0;

        SDA_H;     while (i--)   {         byte <<= 1;         SCL_L;         I2C_delay();         SCL_H;         I2C_delay();         if (SDA_read)    {             byte |= 0x01;         }     }     SCL_L;     return byte; }

    void i2cInit(void) {     GPIO_InitTypeDef gpio;     RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB, ENABLE);

        gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;     gpio.GPIO_Speed = GPIO_Speed_2MHz;     gpio.GPIO_Mode=GPIO_Mode_OUT;   gpio.GPIO_OType= GPIO_OType_OD;   gpio.GPIO_PuPd=GPIO_PuPd_UP;        GPIO_Init(GPIOB, &gpio); }

    bool i2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t len, uint8_t * data)    //µÚÒ»¸ö²ÎÊýÊÇÆ÷¼þµØÖ· reg±íʾҪ¶ÁÈ¡µÃÊý¾ÝµÄ¼Ä´æÆ÷µØÖ· lenÊÇÊý¾Ý³¤¶È  *dataÊÇ´æ´¢¶Á³öÊý¾ÝµÄÖ¸Õë {     int i;     if (!I2C_Start())         return false;     I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);     // ×îºóһλΪ·¢ËÍ»òÕß½ÓÊÕµÄÑ¡Ôñ±ê־λ     if (!I2C_WaitAck()) {         I2C_Stop();         return false;     }     I2C_SendByte(reg);     I2C_WaitAck();     for (i = 0; i < len; i++) {         I2C_SendByte(data[i]);         if (!I2C_WaitAck()) {             I2C_Stop();             return false;         }     }     I2C_Stop();     return true; }

    bool i2cWrite(uint8_t addr, uint8_t reg, uint8_t data) {     if (!I2C_Start())         return false;     I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);     if (!I2C_WaitAck()) {         I2C_Stop();         return false;     }     I2C_SendByte(reg);     I2C_WaitAck();     I2C_SendByte(data);     I2C_WaitAck();     I2C_Stop();     return true; }

    bool i2cRead(uint8_t addr, uint8_t reg, uint8_t len, uint8_t* buf) {     if (!I2C_Start())         return false;     I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);     if (!I2C_WaitAck()) {         I2C_Stop();         return false;     }     while (len)         //½«len³¤¶ÈµÄÕâô¶à×ֽڷŵ½*bufÀï  {     I2C_SendByte(reg);     I2C_WaitAck();     I2C_Start();     I2C_SendByte(addr << 1 | I2C_Direction_Receiver);     I2C_WaitAck();

            *buf = I2C_ReceiveByte();         if (len == 1)             I2C_NoAck();         else             I2C_Ack();         buf++;         len--;         reg++;     }     I2C_Stop();     return true; }

    uint16_t i2cGetErrorCounter(void) {     // TODO maybe fix this, but since this is test code, doesn't matter.     return 0; }

    u8 i2cRead_Reg(uint8_t addr, uint8_t reg) {  u8 a;     if (!I2C_Start())         return false;     I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);     if (!I2C_WaitAck()) {         I2C_Stop();         return false;     }     I2C_SendByte(reg);     I2C_WaitAck();     I2C_Start();     I2C_SendByte(addr << 1 | I2C_Direction_Receiver);     I2C_WaitAck();     a = I2C_ReceiveByte();     I2C_NoAck();     I2C_Stop();     return a; }

    运用MPU6050得根据其寄存器手册来写代码,芯片的默认地址为0X68,下面是MPU的代码:

    uint8_t  mpu6050_buffer[14];      S_INT16_XYZ  GYRO_OFFSET,ACC_OFFSET;     u8 GYRO_OFFSET_OK = 1;  u8 ACC_OFFSET_OK = 1; S_INT16_XYZ  MPU6050_ACC_LAST,MPU6050_GYRO_LAST;   /**************************ʵÏÖº¯Êý******************************************** //½«iic¶ÁÈ¡µ½µÃÊý¾Ý·Ö²ð,·ÅÈëÏàÓ¦¼Ä´æÆ÷    ¼ÓËٶȺͽÇËٶȷֱð¶ÁÈ¡200¸öÈ»ºóȡƽ¾ùÖµ×÷Ϊ³õʼÎó²î  Ëã³öÎó²îºó¾Í²»ÔÙÔËÐмÆËãÎó²îµÄ²¿·Ö *******************************************************************************/ void MPU6050_Dataanl(void)        //ÿִÐÐÒ»´Î¶ÁÈ¡Ò»×éÊý¾Ý   µÚÒ»¸ö200´ÎºóËãÒ»´Îƽ¾ùÖµ×÷ΪÁãƮ֮ºó¾Í²»×Ô¶¯ËãÁãÆ®ÁË {  MPU6050_ACC_LAST.X=((((int16_t)mpu6050_buffer[0]) << 8) | mpu6050_buffer[1]) - ACC_OFFSET.X;   //¼õÈ¥µÄÁãÆ®ÊǵÚÒ»¸ö200msÄÚËã³öµÄ  MPU6050_ACC_LAST.Y=((((int16_t)mpu6050_buffer[2]) << 8) | mpu6050_buffer[3]) - ACC_OFFSET.Y;  MPU6050_ACC_LAST.Z=((((int16_t)mpu6050_buffer[4]) << 8) | mpu6050_buffer[5]) - ACC_OFFSET.Z;  //Ìø¹ýζÈADC  MPU6050_GYRO_LAST.X=((((int16_t)mpu6050_buffer[8]) << 8) | mpu6050_buffer[9]) - GYRO_OFFSET.X;  MPU6050_GYRO_LAST.Y=((((int16_t)mpu6050_buffer[10]) << 8) | mpu6050_buffer[11]) - GYRO_OFFSET.Y;  MPU6050_GYRO_LAST.Z=((((int16_t)mpu6050_buffer[12]) << 8) | mpu6050_buffer[13]) - GYRO_OFFSET.Z;   // if((MPU6050_ACC_LAST.X/8192.0>1.5)||(MPU6050_ACC_LAST.X/8192.0<-1.5))  MPU6050_ACC_LAST.X=0; // if((MPU6050_ACC_LAST.Y/8192.0>1.5)||(MPU6050_ACC_LAST.Y/8192.0<-1.5))  MPU6050_ACC_LAST.Y=0; // if((MPU6050_ACC_LAST.Z/8192.0>1.5)||(MPU6050_ACC_LAST.Z/8192.0<-1.5))  MPU6050_ACC_LAST.Z=0;

     if(!GYRO_OFFSET_OK)  {   static int32_t tempgx=0,tempgy=0,tempgz=0;   static uint8_t cnt_g=0;  // LED1_ON;   if(cnt_g==0)   {    GYRO_OFFSET.X=0;    GYRO_OFFSET.Y=0;    GYRO_OFFSET.Z=0;    tempgx = 0;    tempgy = 0;    tempgz = 0;    cnt_g = 1;    return;   }   tempgx+= MPU6050_GYRO_LAST.X;   tempgy+= MPU6050_GYRO_LAST.Y;   tempgz+= MPU6050_GYRO_LAST.Z;   if(cnt_g==200)   {    GYRO_OFFSET.X=tempgx/cnt_g;    GYRO_OFFSET.Y=tempgy/cnt_g;    GYRO_OFFSET.Z=tempgz/cnt_g;    cnt_g = 0;    GYRO_OFFSET_OK = 1;   // EE_SAVE_GYRO_OFFSET();//±£´æÊý¾Ý    return;   }   cnt_g++;  }  if(!ACC_OFFSET_OK)  {   static int32_t tempax=0,tempay=0,tempaz=0;   static uint8_t cnt_a=0; //  LED1_ON;   if(cnt_a==0)   {    ACC_OFFSET.X = 0;    ACC_OFFSET.Y = 0;    ACC_OFFSET.Z = 0;    tempax = 0;    tempay = 0;    tempaz = 0;    cnt_a = 1;    return;   }   tempax+= MPU6050_ACC_LAST.X;   tempay+= MPU6050_ACC_LAST.Y;  // tempaz+= MPU6050_ACC_LAST.Z;   if(cnt_a==200)   {    ACC_OFFSET.X=tempax/cnt_a;    ACC_OFFSET.Y=tempay/cnt_a;    ACC_OFFSET.Z=tempaz/cnt_a;    cnt_a = 0;    ACC_OFFSET_OK = 1;  //  EE_SAVE_ACC_OFFSET();//±£´æÊý¾Ý    return;   }   cnt_a++;    } }

    /**************************ʵÏÖº¯Êý******************************************** //½«iic¶ÁÈ¡µ½µÃÊý¾Ý·Ö²ð,·ÅÈëÏàÓ¦¼Ä´æÆ÷,¸üÐÂMPU6050_Last *******************************************************************************/ void MPU6050_READ(void)       { // u8 i;  //i2cRead(devAddr,MPU6050_RA_ACCEL_XOUT_H,14,mpu6050_buffer);  mpu6050_buffer[0]=i2cRead_Reg(devAddr,  MPU6050_RA_ACCEL_XOUT_H);  mpu6050_buffer[1]=i2cRead_Reg(devAddr,  MPU6050_RA_ACCEL_XOUT_L);

     mpu6050_buffer[2]=i2cRead_Reg(devAddr,  MPU6050_RA_ACCEL_YOUT_H);  mpu6050_buffer[3]=i2cRead_Reg(devAddr,  MPU6050_RA_ACCEL_YOUT_L);

     mpu6050_buffer[4]=i2cRead_Reg(devAddr,  MPU6050_RA_ACCEL_ZOUT_H);  mpu6050_buffer[5]=i2cRead_Reg(devAddr,  MPU6050_RA_ACCEL_XOUT_L);

     mpu6050_buffer[6]=i2cRead_Reg(devAddr,  MPU6050_RA_TEMP_OUT_H);  mpu6050_buffer[7]=i2cRead_Reg(devAddr,  MPU6050_RA_TEMP_OUT_L);

     mpu6050_buffer[8]=i2cRead_Reg(devAddr,  MPU6050_RA_GYRO_XOUT_H);  mpu6050_buffer[9]=i2cRead_Reg(devAddr,  MPU6050_RA_GYRO_XOUT_L);

     mpu6050_buffer[10]=i2cRead_Reg(devAddr,  MPU6050_RA_GYRO_YOUT_H);  mpu6050_buffer[11]=i2cRead_Reg(devAddr,  MPU6050_RA_GYRO_YOUT_L);

     mpu6050_buffer[12]=i2cRead_Reg(devAddr,  MPU6050_RA_GYRO_ZOUT_H);  mpu6050_buffer[13]=i2cRead_Reg(devAddr,  MPU6050_RA_GYRO_ZOUT_L);

    }

    /**************************ʵÏÖº¯Êý******************************************** *º¯ÊýÔ­ÐÍ:  u8 IICwriteBit(u8 dev, u8 reg, u8 bitNum, u8 data) *¹¦¡¡¡¡ÄÜ:     ¶Á ÐÞ¸Ä Ð´ Ö¸¶¨É豸 Ö¸¶¨¼Ä´æÆ÷Ò»¸ö×Ö½Ú ÖеÄ1¸öλ ÊäÈë dev  Ä¿±êÉ豸µØÖ· reg    ¼Ä´æÆ÷µØÖ· bitNum  ÒªÐÞ¸ÄÄ¿±ê×Ö½ÚµÄbitNumλ data  Ϊ0 ʱ£¬Ä¿±ê뽫±»Çå0 ·ñÔò½«±»ÖÃλ ·µ»Ø   ³É¹¦ Ϊ1 ʧ°ÜΪ0 *******************************************************************************/ void IICwriteBit(u8 dev, u8 reg, u8 bitNum, u8 data){  u8 b;  i2cRead(dev, reg, 1, &b);  b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));  i2cWrite(dev, reg, b); } /**************************ʵÏÖº¯Êý******************************************** *º¯ÊýÔ­ÐÍ:  u8 IICwriteBits(u8 dev,u8 reg,u8 bitStart,u8 length,u8 data) *¹¦¡¡¡¡ÄÜ:     ¶Á ÐÞ¸Ä Ð´ Ö¸¶¨É豸 Ö¸¶¨¼Ä´æÆ÷Ò»¸ö×Ö½Ú ÖеĶà¸öλ ÊäÈë dev  Ä¿±êÉ豸µØÖ· reg    ¼Ä´æÆ÷µØÖ· bitStart  Ä¿±ê×Ö½ÚµÄÆðʼλ length   볤¶È data    ´æ·Å¸Ä±äÄ¿±ê×Ö½ÚλµÄÖµ ·µ»Ø   ³É¹¦ Ϊ1 ʧ°ÜΪ0 *******************************************************************************/ void IICwriteBits(u8 dev,u8 reg,u8 bitStart,u8 length,u8 data) {    u8 b,mask;  i2cRead(dev, reg, 1, &b);   mask = (0xFF << (bitStart + 1)) | 0xFF >> ((8 - bitStart) + length - 1);  data <<= (8 - length);  data >>= (7 - bitStart);  b &= mask;  b |= data;  i2cWrite(dev, reg, b); } /**************************ʵÏÖº¯Êý******************************************** *º¯ÊýÔ­ÐÍ:  void MPU6050_setClockSource(uint8_t source) *¹¦¡¡¡¡ÄÜ:     ÉèÖà MPU6050 µÄʱÖÓÔ´ * CLK_SEL | Clock Source * --------+-------------------------------------- * 0       | Internal oscillator * 1       | PLL with X Gyro reference * 2       | PLL with Y Gyro reference * 3       | PLL with Z Gyro reference * 4       | PLL with external 32.768kHz reference * 5       | PLL with external 19.2MHz reference * 6       | Reserved * 7       | Stops the clock and keeps the timing generator in reset *******************************************************************************/ void MPU6050_setClockSource(uint8_t source){  IICwriteBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source);   } /** Set full-scale gyroscope range. * @param range New full-scale gyroscope range value * @see getFullScaleRange() * @see MPU6050_GYRO_FS_250 * @see MPU6050_RA_GYRO_CONFIG * @see MPU6050_GCONFIG_FS_SEL_BIT * @see MPU6050_GCONFIG_FS_SEL_LENGTH */ void MPU6050_setFullScaleGyroRange(uint8_t range) {  IICwriteBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); }

    /**************************ʵÏÖº¯Êý******************************************** *º¯ÊýÔ­ÐÍ:  void MPU6050_setFullScaleAccelRange(uint8_t range) *¹¦¡¡¡¡ÄÜ:     ÉèÖà MPU6050 ¼ÓËٶȼƵÄ×î´óÁ¿³Ì *******************************************************************************/ void MPU6050_setFullScaleAccelRange(uint8_t range) {  IICwriteBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); } /**************************ʵÏÖº¯Êý******************************************** *º¯ÊýÔ­ÐÍ:  void MPU6050_setSleepEnabled(uint8_t enabled) *¹¦¡¡¡¡ÄÜ:     ÉèÖà MPU6050 ÊÇ·ñ½øÈë˯Ãßģʽ enabled =1   ˯¾õ enabled =0   ¹¤×÷ *******************************************************************************/ void MPU6050_setSleepEnabled(uint8_t enabled) {  IICwriteBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); }

    /**************************ʵÏÖº¯Êý******************************************** *º¯ÊýÔ­ÐÍ:  void MPU6050_setI2CMasterModeEnabled(uint8_t enabled) *¹¦¡¡¡¡ÄÜ:     ÉèÖà MPU6050 ÊÇ·ñΪAUX I2CÏßµÄÖ÷»ú *******************************************************************************/ void MPU6050_setI2CMasterModeEnabled(uint8_t enabled) {  IICwriteBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); }

    /**************************ʵÏÖº¯Êý******************************************** *º¯ÊýÔ­ÐÍ:  void MPU6050_setI2CBypassEnabled(uint8_t enabled) *¹¦¡¡¡¡ÄÜ:     ÉèÖà MPU6050 ÊÇ·ñΪAUX I2CÏßµÄÖ÷»ú *******************************************************************************/ void MPU6050_setI2CBypassEnabled(uint8_t enabled) {  IICwriteBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); }

    void MPU6050_setDLPF(uint8_t mode) {  IICwriteBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode); } /**************************ʵÏÖº¯Êý******************************************** *º¯ÊýÔ­ÐÍ:  void MPU6050_initialize(void) *¹¦¡¡¡¡ÄÜ:     ³õʼ»¯  MPU6050 ÒÔ½øÈë¿ÉÓÃ״̬¡£ *******************************************************************************/ u8 MPU6050_INIT(void) { //  I2C2_Write_1Byte(0xd0,0x19,0x07);//1khz //  I2C2_Write_1Byte(0xd0,0x1a,0x03);//44hzÂ˲¨ //  I2C2_Write_1Byte(0xd0,0x1b,0x00);//gyro 250du/s //  I2C2_Write_1Byte(0xd0,0x1c,0x08);//acc +-4g //  I2C2_Write_1Byte(0xd0,0x24,13);//400khz //  I2C2_Write_1Byte(0xd0,0x6a,0x00);//mst_en=0 //  I2C2_Write_1Byte(0xd0,0x6b,0x00);//sleep=0  MPU6050_REST();  delay_ms(10);  MPU6050_REST();  MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO); //ÉèÖÃʱÖÓ  0x6b   0x01  delay_ms(5);  MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_2000);//ÍÓÂÝÒÇ×î´óÁ¿³Ì +-2000¶ÈÿÃë  delay_ms(5);  MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_4); //¼ÓËٶȶÈ×î´óÁ¿³Ì +-4G  delay_ms(5);  MPU6050_setDLPF(MPU6050_DLPF_BW_42);  delay_ms(5);  MPU6050_setSleepEnabled(0); //½øÈ빤×÷״̬  delay_ms(5);  MPU6050_setI2CMasterModeEnabled(0);  //²»ÈÃMPU6050 ¿ØÖÆAUXI2C  delay_ms(5);  MPU6050_setI2CBypassEnabled(1);  //Ö÷¿ØÖÆÆ÷µÄI2CÓë MPU6050µÄAUXI2C Ö±Í¨¡£¿ØÖÆÆ÷¿ÉÒÔÖ±½Ó·ÃÎÊHMC5883L  delay_ms(5);  return 0;  // //ÅäÖÃMPU6050 µÄÖжÏģʽ ºÍÖжϵçƽģʽ  // IICwriteBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, 0);  // IICwriteBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_OPEN_BIT, 0);  // IICwriteBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_LATCH_INT_EN_BIT, 1);  // IICwriteBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_RD_CLEAR_BIT, 1);  // //¿ªÊý¾Ýת»»Íê³ÉÖÐ¶Ï  //    IICwriteBit(devAddr, MPU6050_RA_INT_ENABLE, MPU6050_INTERRUPT_DATA_RDY_BIT, 1); }

    void MPU6050_REST(void) {      IICwriteBit(devAddr,MPU6050_RA_PWR_MGMT_1,7,1); }

    下面就将数据通过串口1打印出来:  for(a=0;a<14;a++)
      {
       printf("mpu6050_buffer[%d] is %d   ",a ,mpu6050_buffer[a]);
      delay_ms(10);
      }

    小弟也是刚刚玩,希望各位有兴趣的可以交流,欢迎大家指正!谢谢
  • 相关阅读:
    OpenCV(一)
    python中的协程(一)
    python中的协程(三)
    ubuntu18.04 与 python
    js高级
    Django学习笔记5
    Django学习笔记6
    MongoDB 4.03简易使用教程
    python中的协程(二)
    js 词法分析
  • 原文地址:https://www.cnblogs.com/victoryichun/p/3933067.html
Copyright © 2011-2022 走看看