一、关于编译Hi3531 SDK:

之前编译SDK时编译到make uImage总出错,一是找不到.config文件,这个问题是必须先make menuconfig 然后保存.config文件。

二是编译到make uImage的快结束时,会出现找不到mkimage命令错误。

解决方法:

    查看最底层的Makefile:arch/arm/boot/Makefile,可以看到:

   

quiet_cmd_uimage = UIMAGE  $@

      cmd_uimage = $(CONFIG_SHELL) $( MKIMAGE) -A arm -O linux -T kernel \

                   -C none -a $(LOADADDR) -e $(STARTADDR) \

                   -n 'Linux-$(KERNELRELEASE)' -d $< $@

而 MKIMAGE 的值为:

MKIMAGE          := $(srctree)/scripts/mkuboot.sh

所以打开kernel/scripts/mkuboot.sh,修改mkimage的路径,然后编译,就通过了

 

说明:没有权限向公司的编译服务器拷贝mkimage,只能改Makefile中mkimage的路径

2、注意:最好修改osd目录下的Makefile,将删除linux-3.0.x的命令和重新解压的命令去掉,否则每次都

将之前的删除掉再重新解压,所以每次都要修改,没必要,也比较麻烦,编译也很费时间

 

二、关于I2C支持的工作总结

1、开始在SDK里编译的驱动一直没加上,提示:

# insmod gpioi2c.ko

gpioi2c: version magic '3.0.1 SMP mod_unload ARMv7 ' should be '3.0.1 mod_unload ARMv7 '


insmod: can't insert 'gpioi2c.ko': invalid module format

2、但是,SDK里和gpioi2c放一起的实例跑的是正确的结果:

# ./i2c_write 0x56 0x01 0x11

device_addr:0x56; reg_addr:0x 1; reg_value:0x11.

# ./i2c_read 0x56 0x01

device_addr:0x56; reg_addr:0x 1.

0x11

 

# ./i2c_write 0x56 0x02 0x22

device_addr:0x56; reg_addr:0x 2; reg_value:0x22.

# ./i2c_read 0x56 0x02

device_addr:0x56; reg_addr:0x 2.

0x22

读写的数据一致。

说明原来的驱动没有问题,可能是库里的代码有问题。

 

但是还是编译了SDK里的gpioi2c.ko驱动,因为这一个驱动被其他三个驱动使用了,所以需要先rmmod 那三个驱动,然后再卸载这个驱动。

 

3、先说这个问题怎么解决的:

# insmod gpioi2c.ko

gpioi2c: version magic '3.0.1 SMP mod_unload ARMv7 ' should be '3.0.1 mod_unload ARMv7 '


insmod: can't insert 'gpioi2c.ko': invalid module format

这是因为内核配置的不对,修改内核配置项,取消Kernel type->Symmetrical Multi-Processing这一项,编译出的驱动便可以insmod了。


使用了SDK中所带的驱动代码,因为tw2865、tlv_320aic31和sil9024使用了gpioi2c.ko,所以对这四个驱动都重新编译了。

代码存放路径:

[li_xiangping@xn-linux extdrv_hi3531]$ pwd

/home/li_xiangping/Hi3531_SDK_V1.0.2.0/mpp/extdrv_hi3531

         在该路径下执行make,然后将四个子目录w2865、tlv_320aic31、sil9024和gpio_i2c_8b下的.ko文件拷贝到demo板,替换到原来的驱动


4、 对库的修改:

4.1

将I2cWrite()中的:

           if (ioctl(I2cFd, I2C_WRITE, &Value) < 0)

改为:

           if (ioctl(I2cFd, GPIO_I2C_WRITE, &Value) < 0)

 

4.2

将I2cRead()中的:

if (ioctl(I2cFd, GPIO_I2C_READ, &Value) < 0)

改为:

                  if (ioctl(I2cFd, GPIO_I2C_READ, &Value) < 0)

4.3

在Inner/i2c.h中添加:

#define GPIO_I2C_READ               0x01

#define GPIO_I2C_WRITE                 0x03

 

修改原因:

 ioctl()的cmd值不一致,导致I2cWrite()失败。

写的时候总失败,读出来的数据是正确的,因为原来定义的宏是:

#define I2C_READ               0x01

#define I2C_WRITE                 0x02

修改后便正确了

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

#include <linux/kernel.h>

#include <linux/module.h>



#include <linux/i2c.h>

#include <linux/init.h>

#include <linux/time.h>

#include <linux/interrupt.h>

#include <linux/delay.h>

#include <linux/errno.h>

#include <linux/err.h>

#include <linux/platform_device.h>

#include <linux/clk.h>

#include <linux/cpufreq.h>

#include <linux/slab.h>

#include <linux/io.h>

#include <linux/miscdevice.h>

#include <linux/fcntl.h>

#include <linux/proc_fs.h>

#include <linux/workqueue.h>



#include <asm/uaccess.h>

#include <asm/system.h>

#include <asm/io.h>

#include <asm/irq.h>



#define DEV_NAME                 "mic i2c driver"

#define DRV_VERSION              "1.0.0"



#define I2C_WAIT_TIME_OUT       0x1000

#define I2C_ADRESS_BASE         0x200D0000

#define I2C_ADRESS_PHY_LEN      0x20



#define MIC_I2C_CLOCK           (110000000)

#define MIC_I2C_RATE            (100000)



#define READ_OPERATION          (1)

#define WRITE_OPERATION         0xfe



/* the offset of reg */

#define I2C_CTRL_REG            0x000

#define I2C_COM_REB             0x004

#define I2C_ICR_REG             0x008

#define I2C_SR_REG              0x00C

#define I2C_SCL_H_REG           0x010

#define I2C_SCL_L_REG           0x014

#define I2C_TXR_REG             0x018

#define I2C_RXR_REG             0x01C



/* I2C_CTRL_REG */

#define I2C_ENABLE             (1 << 8)

#define I2C_UNMASK_TOTAL       (1 << 7)

#define I2C_UNMASK_START       (1 << 6)

#define I2C_UNMASK_END         (1 << 5)

#define I2C_UNMASK_SEND        (1 << 4)

#define I2C_UNMASK_RECEIVE     (1 << 3)

#define I2C_UNMASK_ACK         (1 << 2)

#define I2C_UNMASK_ARBITRATE   (1 << 1)

#define I2C_UNMASK_OVER        (1 << 0)

#define I2C_UNMASK_ALL         (I2C_UNMASK_START | I2C_UNMASK_END |      \

                                    I2C_UNMASK_SEND | I2C_UNMASK_RECEIVE |   \

                                    I2C_UNMASK_ACK | I2C_UNMASK_ARBITRATE |  \

                                    I2C_UNMASK_OVER)



/* I2C_SR_REG */

#define I2C_BUSY           (1 << 7)

#define I2C_START_INTR     (1 << 6)

#define I2C_END_INTR       (1 << 5)

#define I2C_SEND_INTR      (1 << 4)

#define I2C_RECEIVE_INTR   (1 << 3)

#define I2C_ACK_INTR       (1 << 2)

#define I2C_ARBITRATE_INTR (1 << 1)

#define I2C_OVER_INTR      (1 << 0)



/* I2C_ICR_REG */

#define I2C_CLEAR_START (1 << 6)

#define I2C_CLEAR_END (1 << 5)

#define I2C_CLEAR_SEND (1 << 4)

#define I2C_CLEAR_RECEIVE (1 << 3)

#define I2C_CLEAR_ACK (1 << 2)

#define I2C_CLEAR_ARBITRATE (1 << 1)

#define I2C_CLEAR_OVER (1 << 0)

#define I2C_CLEAR_ALL (I2C_CLEAR_START | I2C_CLEAR_END | \

                       I2C_CLEAR_SEND | I2C_CLEAR_RECEIVE | \

                       I2C_CLEAR_ACK | I2C_CLEAR_ARBITRATE | \

                       I2C_CLEAR_OVER)



/* I2C_COM_REB */

#define I2C_SEND_ACK       (~(1 << 4))

#define I2C_START          (1 << 3)

#define I2C_READ           (1 << 2)

#define I2C_WRITE          (1 << 1)

#define I2C_STOP           (1 << 0)



#define  mic_i2c_write(addr, value) ((*(volatile unsigned int *)(addr)) = (value))

#define  mic_i2c_read(addr)         (*(volatile unsigned int *)(addr))



#define MUXCTRL_REG102   IO_ADDRESS(0x200f0000 + 0x198) // I2C_SDA

#define MUXCTRL_REG103   IO_ADDRESS(0x200f0000 + 0x19c) // I2C_SCL



/* i2c controller state */

enum mic_i2c_state {

        STATE_IDLE,

        STATE_START,

        STATE_READ,

        STATE_WRITE,

        STATE_STOP

};



enum mic_i2c_type {

        TYPE_MIC_I2C,

        TYPE_MIC_NULL,

};



struct mic_i2c {

        spinlock_t                lock;

        wait_queue_head_t        wait;

        struct i2c_msg                *msg;

        unsigned int                irq;



        enum mic_i2c_state        state;

        unsigned long                clkrate;



        void __iomem                *regs;

        struct clk                    *clk;

        struct device                *dev;

        struct resource                *ioarea;

        struct i2c_adapter        adap;

};



struct resource mic_i2c_resource[] = {      

[0]={                                                  

  .start =  I2C_ADRESS_BASE,           

  .end   =  I2C_ADRESS_BASE + I2C_ADRESS_PHY_LEN,           

  .flags =  IORESOURCE_MEM,           

  }

};



static short mic_poll_status(struct i2c_adapter *adap, unsigned long bit)

{

        int loop_cntr = 10000;

        unsigned int reg = 0x00;

        struct mic_i2c *i2c = container_of(adap, struct mic_i2c, adap);



        do {

                udelay(10);

        } while (!(reg = mic_i2c_read(i2c->regs + I2C_SR_REG) & bit) && (--loop_cntr > 0));

       

        mic_i2c_write((i2c->regs + I2C_ICR_REG),  I2C_CLEAR_ALL);



        loop_cntr = 10000;

    while((mic_i2c_read(i2c->regs + I2C_SR_REG) & I2C_ACK_INTR) && (--loop_cntr > 0));

       

        return loop_cntr;

}



static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)

{

    struct mic_i2c *i2c = container_of(adap, struct mic_i2c, adap);



        /* Read data */

        while(length) {

                /* Send Start */

                if(length - 1)

            mic_i2c_write((i2c->regs + I2C_COM_REB), I2C_READ);

                else

            mic_i2c_write((i2c->regs + I2C_COM_REB), I2C_READ | (~I2C_SEND_ACK));

               

                if(!mic_poll_status(adap, I2C_RECEIVE_INTR)) {

                        dev_info(&adap->dev, "TXRDY timeout\n");                       


                    return -ETIMEDOUT;

                        }



                *buf++ = (mic_i2c_read(i2c->regs + I2C_RXR_REG) & 0xff);

                length--;

                }



        mic_i2c_write((i2c->regs + I2C_ICR_REG), I2C_STOP);       



        return 0;

}



static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)

{

    struct mic_i2c *i2c = container_of(adap, struct mic_i2c, adap);

         

        while(length--)

                {

            mic_i2c_write((i2c->regs + I2C_TXR_REG), *buf++);

            mic_i2c_write((i2c->regs + I2C_COM_REB), I2C_WRITE);



                   if(!mic_poll_status(adap, I2C_OVER_INTR))

                {

                dev_dbg(&adap->dev, "TXRDY timeout\n");                       

                    return -ETIMEDOUT;

                       }

           }

      

        return 0;

}



/*

* first port of call from the i2c bus code when an message needs

* transferring across the i2c bus.

*/

static int mic_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num)

{

    int i, ret;

        unsigned char device_addr = 0x00;

        struct mic_i2c *i2c = container_of(adap, struct mic_i2c, adap);



        for(i = 0; i < num; i++) {  

            mic_i2c_write((i2c->regs + I2C_COM_REB),  I2C_WRITE | I2C_START);



                if((pmsg->addr >> 8) & 0x00ff) {

                       device_addr = (char)((pmsg->flags & I2C_M_RD) ? ((pmsg->addr >> 8) | READ_OPERATION) : ((pmsg->addr >> 8) & WRITE_OPERATION));

                       xfer_write(adap, &device_addr, 1);

                        device_addr = (char)((pmsg->flags & I2C_M_RD) ? (pmsg->addr | READ_OPERATION) : (pmsg->addr & WRITE_OPERATION));

                       xfer_write(adap, &device_addr, 1);

                    }

                else {

                        device_addr = (char)((pmsg->flags & I2C_M_RD) ? (pmsg->addr | READ_OPERATION) : (pmsg->addr & WRITE_OPERATION));

            xfer_write(adap, &device_addr, 1);

                        }



                pmsg->addr = device_addr;

                       

                if (pmsg->len && pmsg->buf) {        /* sanity check */

                        if (pmsg->flags & I2C_M_RD)

                                ret = xfer_read(adap, pmsg->buf, pmsg->len);

                        else

                                ret = xfer_write(adap, pmsg->buf, pmsg->len);

                       }



                /* Wait until transfer is finished */

                mic_i2c_write((i2c->regs + I2C_COM_REB), I2C_STOP);

                if(!mic_poll_status(adap, I2C_OVER_INTR)) {

                 dev_info(&adap->dev, "TXRDY timeout\n");                       

                     return -ETIMEDOUT;



                mic_i2c_write((i2c->regs + I2C_ICR_REG), 0x01);



                if(ret < 0)

                        return ret;

                }

            pmsg++;                /* next message */       

        }



        return i;

}



/* declare our i2c functionality */

static u32 mic_i2c_func(struct i2c_adapter *adap)

{

    printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);

       

        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;

}

/* i2c bus registration info */

static const struct i2c_algorithm mic_i2c_algorithm = {

        .master_xfer                = mic_i2c_xfer,

        .functionality                = mic_i2c_func,

};



static int mic_i2c_probe(struct platform_device *pdev)

{

    struct mic_i2c *i2c;       

        int ret;

        unsigned int  value, value_h, value_l;   



        writel(0x01, MUXCTRL_REG102);

        writel(0x01, MUXCTRL_REG103);

   

        i2c = kzalloc(sizeof(struct mic_i2c), GFP_KERNEL);

        if (!i2c) {

                dev_err(&pdev->dev, "no memory for state\n");

                return -ENOMEM;

        }



        snprintf(i2c->adap.name, sizeof(i2c->adap.name), "mic");       

        i2c->adap.algo = &mic_i2c_algorithm;       

        i2c->adap.class = I2C_CLASS_HWMON;       

        i2c->adap.dev.parent = &pdev->dev;

        i2c->adap.nr = pdev->id;

       

        i2c->ioarea = platform_get_resource(pdev, IORESOURCE_MEM, 0);

        if (!i2c->ioarea)

                return -ENXIO;



        if (!request_mem_region(i2c->ioarea->start, resource_size(i2c->ioarea), "mic_i2c"))

                return -EBUSY;



        i2c->regs = ioremap(i2c->ioarea->start, resource_size(i2c->ioarea));

        if (!i2c->regs) {

                ret = -ENOMEM;

                goto fail0;

        }



        spin_lock_init(&i2c->lock);



        /* clk */

        /* Read CTRL */   

        value = mic_i2c_read(i2c->regs + I2C_CTRL_REG);



        /* maskable interrupt of i2c */   

        mic_i2c_write((i2c->regs + I2C_CTRL_REG), (value & (~I2C_UNMASK_TOTAL)));   


        value_h = (MIC_I2C_CLOCK / (MIC_I2C_RATE * 2)) / 2 - 1;   

        mic_i2c_write((i2c->regs + I2C_SCL_H_REG), value_h);

       

        value_l = (MIC_I2C_CLOCK / (MIC_I2C_RATE * 2)) / 2 - 1;   

        mic_i2c_write((i2c->regs + I2C_SCL_L_REG), value_l);   

       

        /* enable interrupt of i2c */   

        mic_i2c_write((i2c->regs + I2C_ICR_REG),  0x03);

        mic_i2c_write((i2c->regs + I2C_CTRL_REG), 0x0187 | value);

       

        platform_set_drvdata(pdev, i2c);



        ret = i2c_add_numbered_adapter(&i2c->adap);

        if (ret) {

                dev_err(&pdev->dev, "Adapter %s registration failed\n",

                                i2c->adap.name);

                goto fail1;

        }



        dev_info(&pdev->dev, "mic i2c bus driver.\n");



        return 0;



fail1:       

        platform_set_drvdata(pdev, NULL);       

       

fail0:

        release_mem_region(i2c->ioarea->start, resource_size(i2c->ioarea));

        iounmap(i2c->regs);

        kfree(i2c);       



        return ret;         

}



static int __devexit mic_i2c_remove(struct platform_device *pdev)

{

        struct mic_i2c *i2c = platform_get_drvdata(pdev);

       

    printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);



        i2c_del_adapter(&i2c->adap);

        platform_set_drvdata(pdev, NULL);

        release_mem_region(i2c->ioarea->start, resource_size(i2c->ioarea));

        iounmap(i2c->regs);

    kfree(i2c);

       

        return 0;

}



#ifdef CONFIG_PM_RUNTIME

static int mic_i2c_suspend_noirq(struct device *dev)

{

        printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);



        return 0;

}



static int mic_i2c_resume(struct device *dev)

{

        printk(KERN_ALERT "%s:%s,%s\r\n", __FUNCTION__,__DATE__,__TIME__);



        return 0;

}



static const struct dev_pm_ops mic_i2c_dev_pm_ops = {

        .suspend_noirq = s3c24xx_i2c_suspend_noirq,

        .resume = mic_i2c_resume,

};



#define MIC_DEV_PM_OPS (&mic_i2c_dev_pm_ops)

#else

#define MIC_DEV_PM_OPS NULL

#endif



static void mic_i2c_release(struct device * dev)

{

}



struct platform_device mic_i2c_device = {

        .name                  = "mic-i2c",

        .id                          = 0,

        .num_resources          = ARRAY_SIZE(mic_i2c_resource),

        .resource              = mic_i2c_resource,

        .dev              =

        {           

         .release           =  mic_i2c_release,

        }  

};



static struct platform_driver mic_i2c_driver = {

        .probe                = mic_i2c_probe,

        .remove                = mic_i2c_remove,

        .driver                = {

                .owner        = THIS_MODULE,

                .name        = "mic-i2c",

                .pm        = MIC_DEV_PM_OPS,

        },

};



static int __init mic_i2c_init(void)

{

    int ret = -ENODEV;



        printk(KERN_INFO "%s %s V%s\n", __func__, DEV_NAME, DRV_VERSION);



    platform_device_register(&mic_i2c_device);

       

    ret = platform_driver_register(&mic_i2c_driver);

        if(ret)

                {

                platform_device_unregister(&mic_i2c_device);

                printk("platform_device_register is fail!\n");

                goto end;

                }

       

end:       

        return ret;  

}

subsys_initcall(mic_i2c_init);



static void __exit mic_i2c_exit(void)

{

    printk(KERN_INFO "%s %s V%s\n", __func__, DEV_NAME, DRV_VERSION);

       

        platform_driver_unregister(&mic_i2c_driver);

        platform_device_unregister(&mic_i2c_device);



}

module_exit(mic_i2c_exit);



MODULE_DESCRIPTION("mic i2c driver");

MODULE_AUTHOR("microcreat <microcreat@gmail.com>");

MODULE_LICENSE("GPL");

直接可以编译成ko,加载进内核,进入内核可以看到i2c设备成功加载!

hi3531的i2c部分的更多相关文章

  1. I2C子系统之驱动SSD1306 OLED

    理解I2C设备驱动框架,主要围绕四个结构体去分析就容易了. struct i2c_algorithm:提供I2C协议的实现的操作,如:master_xfer实现数据收发的最基本方法. struct i ...

  2. AM335x kernel 4.4.12 i2c eeprom AT24c02驱动移植

    kernel 4.4.12 i2c eeprom AT24c02驱动移植 在kernel make menuconfig ARCH=ARM 中打开: Device Drivers ---> Mi ...

  3. I2C基础知识

    常识 两条总线线路:串行数据总线SDA,串行时钟总线SCL 每个连接到总线的器件都有唯一的地址供其他设备寻址 每个连接到总线的器件都可以作为发送器和接收器 是多主机总线,如果两个或更多主机同时初始化, ...

  4. I2C 基础原理详解

    今天来学习下I2C通信~ I2C(Inter-Intergrated Circuit)指的是 IC(Intergrated Circuit)之间的(Inter) 通信方式.如上图所以有很多的周边设备都 ...

  5. i2c协议

    i2c协议 http://blog.csdn.net/g_salamander/article/details/8016698 总线设备驱动模型 http://blog.csdn.net/u01395 ...

  6. I2S/PCM/IOM-2、I2C/SPI/UART/GPIO/slimbus

    概述 I2S,PCM,IOM-2都是数字音频接口,传数据的. I2C,SPI,UART,GPIO是控制接口,传控制信令的. I2S I2S(Inter-IC Sound Bus)是飞利浦公司为数字音频 ...

  7. I2C总线(异步)

    起始位与停止位的定义: 起始信号:当SCL为高期间,SDA由高到低的跳变:启动信号是一种电平跳变时序信号,而不是一个电平信号. 停止信号:当SCL为高期间,SDA由低到高的跳变:停止信号也是一种电平跳 ...

  8. Uart、SPI和I2C的区别

    串口通信:UART.SPI.I2C区别[引用]   1.UART就是两线,一根发送一根接收,可以全双工通信,线数也比较少.数据是异步传输的,对双方的时序要求比较严格,通信速度也不是很快.在多机通信上面 ...

  9. Raspberry Pi I2C驱动 (Python)

    本文参考 http://www.instructables.com/id/Raspberry-Pi-I2C-Python/all/?lang=zh 作者 AntMan232 In this instr ...

随机推荐

  1. 安装pcntl以实现php多进程

    pcntl 扩展包一般就在php源码的ext目录下. cd ./ext/pcntl /opt/server/php5/bin/phpize ./configure \ --with-php-confi ...

  2. CTSC 2017 滚粗记

    CTSC 2017 滚粗记 结束好几天了一直没写. 明天就要去参加二轮省选了,填一下坑吧. 所以可能很多东西已经忘了 Day -2 [5.5 Fri] 周五晚上是其他学信竞的同学来机房的时间... 也 ...

  3. Win10无法使用小娜搜索本地应用问题的解决方案

    小娜介绍 win10的Cortana小娜是一个功能非常强大的语音和搜索助手,用户可以通过小娜助手搜索任意的文件和应用软件,不过有用户发现win10的小娜搜索不到已安装的本地软件,那么win10小娜助手 ...

  4. Python数据结构之二——tuple(元组)

    Python版本:3.6.2  操作系统:Windows  作者:SmallWZQ 列表和元组是Python中最常见的内建序列.元组与列表一样,但是tuple一旦创建就不能修改.创建元组的语法非常简单 ...

  5. React项目模板-从项目搭建到部署

    前一段时间做了一个小项目,时间比较紧,就一个人月.最终希望能够通过微信公众号链接启动应用. 项目的业务细节就不多说了,主要是想分享一下做这个项目技术方面的一些经验. 技术选型 参考范围大致三种:Ang ...

  6. 使用腾讯云“自定义监控”监控GPU使用率

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:李想 随着人工智能以及比特币的火热,GPU云服务的使用场景是越来越广,在很多场景下我们也需要获取GPU服务器的性能参数来优化程序的执行.目 ...

  7. go 开发环境安装教程 windows

         首先进入go 语言官网下载最新安装包,我目前安装的版本是 1.8.3版本:go1.8.3.windows-amd64.msi 如果下载慢,这个是百度云地址:https://pan.baidu ...

  8. Python3实现QQ机器人自动爬取百度文库的搜索结果并发送给好友(主要是爬虫)

    一.效果如下: 二.运行环境: win10系统:python3:PyCharm 三.QQ机器人用的是qqbot模块 用pip安装命令是: pip install qqbot (前提需要有request ...

  9. Java经典编程题50道之三十九

    写一个函数,求一个字符串的长度,在main函数中输入字符串,并输出其长度. public class Example39 {    public static void main(String[] a ...

  10. java9 - 异常处理

    Java异常 1.异常初见 System.out.println(1/0); 运行上面语句之后打印出: Exception in thread "main" java.lang.A ...