精华内容
下载资源
问答
  • c语言结构体学习整理(结构体初始化,结构体指针)

    万次阅读 多人点赞 2018-11-01 20:22:12
    请注意,在我们进行数组初始化的时候如果定义的数组过长,而我们只初始化了一部分数据,对于未初始化的数据如果是数值型,则会自动赋值为0,对于字符型,会自动赋初值为NULL,即‘\0’ 即不足的元素补以默认值 这里...

    渣渣c的c语言学习之路

    1.关于c语言的结构体:

    首先我们为什么要用到结构体,我们都已经学了很多int char …等类型还学到了同类型元素构成的数组,以及取上述类型的指针,在一些小应用可以灵活使用,然而,在我们实际应用中,每一种变量进行一次声明,再结合起来显然是不太实际的,类如一位学生的信息管理,他可能有,姓名(char),学号(int)成绩(float)等多种数据。如果把这些数据分别单独定义,就会特别松散、复杂,难以规划,因此我们需要把一些相关的变量组合起来,以一个整体形式对对象进行描述,这就是结构体的好处。

    2首先我们要了解一些小知识

    2.1**只有结构体变量才分配地址,而结构体的定义是不分配空间的。**
    2.2结构体中各成员的定义和之前的变量定义一样,但在定义时也不分配空间。
    2.3结构体变量的声明需要在主函数之上或者主函数中声明,如果在主函数之下则会报错
    2.4c语言中的结构体不能直接进行强制转换,只有结构体指针才能进行强制转换
    2.5相同类型的成员是可以定义在同一类型下的
    列如

    
    struct Student
    { 
    	int number,age;//int型学号和年龄
    	char name[20],sex;//char类型姓名和性别
    	float score;
    }

    最后的分号不要忘了 有的编译器会自动加上,因此有的同学就会不注意。

    3关于结构体变量的定义和引用

    在编译时,结构体的定义并不分配存储空间,对结构体变量才按其数据结构分配相应的存储空间

    
     struct Book
     { 
     	char title[20];//一个字符串表
    
    示的titile 题目
    	char author[20];//一个字符串表示的author作者
     	float value;//价格表示 
     };//这里只是声明 结构体的定义 
    struct Book book1,book2;//结构体变量的定义 分配空间
    
    book1.value;//引用结构体变量
    

    定义结构体变量以后,系统就会为其分配内存单元,比如book1和book2在内存中占44个字节(20+20+4)具体的长度你可以在你的编译器中使用sizeof关键字分别求出来。
    列如

    当然,要注意一点:用sizeof关键字求结构体长度时,返回的最大基本类型所占字节的整数倍 比方说我们上面求得的为44 为 float(4个字节)的整数倍,
    但是我们把title修改为title[22]; 这时正常长度为46 ,但是你会发现实际求得的为48,(4的整数倍)

    这就涉及到结构体的存储

    1结构体整体空间是占用空间最大的成员(的类型)所占字节数的整数倍。

    2.结构体的每个成员相对结构体首地址的偏移量(offset)都是最大基本类型成员字节大小的整数倍,如果不是编译器会自动补齐,

    关于这个我们简单介绍下:

    1.偏移量----偏移量指的是结构体变量中成员的地址和结构体变量首地址的差。即偏移字节数,结构体大小等于最后一个成员的偏移量加上他的大小,第一个成员的偏移量为0,

    struct S1
    {
        char a;
    
        int b;
    
        double c;
    };
    

    这里char a 偏移量为1 之后为int b 因为偏移量1不为int(4)的整数倍,所以会自动补齐,而在 double c 时,偏移量为8 是double(8)的整数倍,所以不用自动补齐 最后求得结构体得大小为 16

    具体看下图:
    在这里插入图片描述
    通过上面的代码同学们应该会有一个简单的认知

    4结构体变量的初始化

    结构体的初始化有很多需要注意的地方,这里我们说明下
    首先是几种初始化的方法
    ps在对结构体变量初始化时,要对结构体成员一一赋值,不能跳过前面成员变量,而直接给后面成员赋初值,但是可以只赋值前面几个,对与后面未赋值的变量,如果是数值型,则会自动赋值为0,对于字符型,会自动赋初值为NULL,即‘\0’

    4.1定义时直接赋值

    struct Student
    { 
    	char name[20];
    	char sex;
    	int number;
    }stu1={"zhaozixuan",'M',12345};
    //或者
    struct Student
    { 
    	char name[20];
    	char sex;
    	int number;
    }struct Student stu1={"zhaozixuan",'M',12345};
    
    

    注意字符为‘ ’ 字符串为""
    4.2定义结构体之后逐个赋值

    stu1.name="王伟";
    stu1.sex='M';
    stu1.number=12305;
    //也可用strcpy函数进行赋值
    strcpy(stu1.name,"王伟");
    
    

    4.3定义之后任意赋值

     struct Student stu1={
      .name="Wang",
      .number=12345,
      .sex='W', 
     };//可以对任意变量赋值
    

    这样写的好处时不用按照顺序来进行初始化,而且可以对你想要赋值的变量直接进行赋值,而不想赋值的变量可以不用赋值

    需要注意的是如果在定义结构体变量的时候没有初始化,那么后面就不能全部一起初始化了;

    等下结构体数组初始化时我们还会有一个讲解

    这里我们顺带提一下typedef说明结构体类型


    这里的BOOK就相当于struct book的一个别名一样,用它来定义结构体变量非常简便
    主要也是考二级要用到,所以我们简单介绍下

    5结构体变量的引用(输出和输入)

    5.1结构体变量的赋值用scanf赋值和printf输出时跟其他变量操作一样
    但是有几点需要注意
    (1) .是运算符,在所有运算符优先级中最高
    (2)如果结构体的成员本身是一个结构体,则需要继续用.运算符,直到最低一级的成员。

    struct Student
    {	char name[20];
    	char sex;
    	int number;
    	struct Date
    	{
    		int year;
     		int month;
     		int day;
    	}birthday;
    
    }stu1;
    printf("%d",stu1.birthday);//这样子是错误的,因为birthday也是一个结构体变量
    scanf("%d",&stu1.birthday.month);//正确
    

    (3)可以引用接头体变量成员的地址,也可以引用结构体变量的地址:

    printf("%o", student);(输出student的首地址)(%o 按八进制输出)

    6结构体数组及其初始化(重点)

    这里我们简单说下,具有相同类型的结构体变量组成数组就是结构体数组

    结构体数组与结构体变量区别只是将结构体变量替换为数组

    struct Student
    { 
    	char name[20];
    	char sex;
    	int number;
    }stu1[5]={
    	 {"zhaozixuan",'M',12345},
    	 {"houxiaohong",'M',12306},
    	 {"qxiaoxin",'W',12546},
    	 {"wangwei",'M',14679},
    	 {"yulongjiao",'W',17857}
    };
    stu1[3].name[3]//表示stu1的第三个结构变量中姓名的第五个字符
    //若初始化时已经是结构体数组全部元素[]中的数可以不写如stu1[]=
    

    注意结构体数组要在定义时就直接初始化,如果先定义再赋初值是错误的
    比如:

    struct Student stu1;
    stu1[3]={
      {"zhaozixuan",'M',12345},
      {"houxiaohong",'M',12306},
      {"qxiaoxin",'W',12546}
      };
      
    

    这样子是错误的,

    这里我在写的时候遇到一些问题,还是结构体数组初始化的问题,折腾了下解决了,给大家分享下
    对于数组初始化时
    比如

    char str[20];
    str="I love you";/* 这样会修改数组的地址,但是数组的地址分配之后是不允许改变的 */
    
    

    在第一条语句中 str就已经被定义成数组而在C99标准中不允许将字符串(实际上是一个指针变量) 赋值给数组,所以如果我们直接赋值是错误的

    那么怎么弄呢
    这里提供3种方法

    1.定义数组时直接定义
    char str[20]=“I love you”;

    2.用strcpy或者memset函数进行复制
    char str[20];
    strcpy(str,“I love you”);
    再用到memset函数时,出现了一些问题
    对于memcset函数简单介绍下

    memset
    void *memset(void *s,int c,size_t n)
    作用:将已开辟内存空间s的首n个字节的值设为值c。

    char str[20];
    memset(str,'a',20);
    

    如果是字符类型数组的话,memset可以随便用,但是对于其他类型的数组,一般只用来清0或者填-1,如果是填充其他数据就会出错

    int str[10];
    memset(str,1,sizeof(str));//这样是错误的
    
    

    这里我们说下这个错误,

    首先我们要知道memset在进行赋值时,是按字节为单位来进行赋值的,每次填充的数据长度为一个字节,而对于其他类型的变量,比如int,占4个字节 所以sizeof(str)=40; 而用memset赋值时,将会对指向str地址的前40个字节进行赋值0x01(00000001) 的操作,把0x00000000赋值4次0x01操作变为0x01010101(00000001000000010000000100000001)

    相当于给“前10个int”进行了赋值0x01010101的操作 对应十进制的16843009
    所以会出很大的错误

    这里请务必要注意,但是如果是清零一个数组用memset还是很方便的
    简单使用的话同学们用strcmp函数就行

    3用指针(注意内存分配)
    char *str;
    str=“I love you”;

    这两句话的本质是,在内存中开辟一段内存空间,把"I love you"放进这段内存空间,然后把这段内存空间的地址交给str,由于str是变量,所以给它赋值是合法的。

    请注意,在我们进行数组初始化的时候如果定义的数组过长,而我们只初始化了一部分数据,对于未初始化的数据如果是数值型,则会自动赋值为0,对于字符型,会自动赋初值为NULL,即‘\0’ 即不足的元素补以默认值
    这里我们在4小节中也提到了
    比如

    int str[10]={1};//这里只是把str的第一个元素赋值为1,其他元素默认为0
    
    



    7结构体与指针

    我们知道,指针指向的是变量所占内存的首地址,在结构体中,指针指向的是结构体变量的起始地址,当然也可指向结构体变量的元素
    这里我们分为三部分
    7.1指向结构体变量的指针

    定义形式一般为
    struct 结构体名* 指针名;
    比如: struct Student* p;

    struct Student
    {	
    	char cName[20];
     	int number;
     	char csex;  
    }student1;
    struct Student*p;
    p=&student1;
    //若为结构体数组则
    struct Student stu1[5];
    struct Student*p;
    p=stu1;//因为stu1为结构体数组而p=stu1直接是指向stu1的首地址,就不用再加&符
    
    

    用结构体指针变量访问结构体变量成员有以下两种方式:
    (*p).cName //这里的括号不能少,在5.1中有提到
    p->cName

    简单来说以下三种形式是等价的

    p->cName
    (*p).cName 
    student1.cName
    p->cName //可以进行正常的运算
    

    p->number++; 是将结构体变量中number的值进行运算,然后再加一,
    这里要注意下,等下在7.2中会有比较

    7.2指向结构体数组的指针

    7.1中我们已经提到结构体数组指针的命名,这里我们仅对一些知识点做下介绍
    这里我们接着来说结构体数组指针
    在我们想要用指针访问结构体数组的第n个数据时可以用

    struct Student stu1[5];
    struct Student*p;
    p=stu[n];
    (++p).number//是指向了结构体数组下一个元素的地址
    
    

    7.3结构体成员是指针类型变量
    比如

    struct Student
    {
     	char* Name;//这样防止名字长短不一造成空间的浪费
     	int number;
     	char csex;  
    }student1;
    
    

    在使用时可以很好地防止内存被浪费,但是注意在引用时一定要给指针变量分配地址,如果你不分配地址,结果可能是对的,但是Name会被分配到任意的一的地址,结构体不为字符串分配任何内存存储空间具有不确定性,这样就存在潜在的危险,

    struct Student
    {
     	char* Name;
     	int number;
     	char csex;  
    }stu,*stu;
    
    stu.name=(char*)malloc(sizeof(char));//内存初始化
    

    这里我们说一下,同学们看书的时候一般不会看到,
    如果我们定义了结构体指针变量,他没有指向一个结构体,那么这个结构体指针也是要分配内存初始化的,他所对应的指针类型结构体成员也要相应初始化分配内存

    struct Student
    {
     	char* Name;
     	int number;
    	char csex;  
    }stu,*stu;
    stu = (struct student*)malloc(sizeof(struct student));./*结构体指针初始化*/
      stu->name = (char*)malloc(sizeof(char));/*结构体指针的成员指针同样需要初始化*/  
    
    

    7.4二叉树遍历算法
    二叉树的二叉链表类型定义如下:
    typedef struct btnode {
    datatype data;
    struct btnode *lchild,*rchild;
    };
    这里我们仅仅提出以下,因为涉及到链表,感兴趣的同学可以去学习下(二级要用),
    7.5结构体作为函数参数

    首先我们要注意的一点,使用结构体变量作为函数参数的时候,采取的是值传递的方式,将结构体所占内存单元的内容全部传递给形参,并且形参必须也要是同类型的结构体变量,在使用时,会自动创建一个结构体变量作为原变量的副本,并且也需要占内存,并且在调用期间如果修改(形参)结构体中成员的值,修改值是无效的

    而如果用指针作为实参,传递给函数的形参,这时候传递的是结构体的地址,形参所指向的地址就是结构体变量的地址,这时候进行修改的话是可以修改的,这正是指针的精华所在

    在这里我们再提供几种互换两个结构体的方法

    struct Student
    {
     char cName[20];
     int number;
     char csex;  
    }student1,student2;
    struct Student student1={"Wang",12345,'W'};
    struct Student student2={"Zhao",54321,'M'}; 
    struct Student*stu1=&student1;
    struct Student*stu2=&student2;
    
    struct Student *student3;
    student3=stu1;
    stu1=stu2;
    stu2=student3;//互换地址
    
    2对于同类型结构体直接互换值就行
    struct stu student3;
    student3=student1;
    student1=student2;
    student2=student3;
    //这里也可以写成应strcmp函数互换
    
    3memcpy()函数进行互换
    
    
    4比较笨的方法: 用for循环互换
    

    最后提下memset清空结构体

    struct Student
    {
     char cName[20];
     int number;
     char csex;  
    }stu1;
    
    一般情况下,清空str的方法:
      str.cName[0]='\0';
      str.csex='0';
      str.number=0;
      但是我们用memset就非常方便:
      memset(&str,0,sizeof(struct Student));
      如果是数组:
      struct Student stu[10];
      就是
      memset(stu,0,sizeof(struct Student)*10);
    

    整理不易,点个赞再走呗!

    展开全文
  • 1.项目运行 cd projectname npm run dev 报错:'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序 或批处理文件。 解决:重新npm install ... 解决1:npm cache clean --forc...

    1.项目运行

    cd projectname

    npm run dev

    报错:'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    解决:重新npm install

                    报错1:npm ERR! code Z_BUF_ERROR

                   解决1:npm cache clean --force,然后再npm install,报错2,失败(网上有人此步成功)

                   报错2:npm ERR! errno -4048,Error: EPERM: operation not permitted,

                   解决2.1:镜像文件损坏,重新下载安装镜像文件:npm install -g cnpm --registry=https://registry.npm.taobao.org,再执行 npm install,还报错,失败(网上有人此步可以)

                   解决2.2:需要删除npmrc文件。强调:不是nodejs安装目录npm模块下的那个npmrc文件,而是在C:\Users\{账户}\下的.npmrc文件.(引用网友的原话),再执行npm install(成功)!!!

    结果:

     

     

     

     

    展开全文
  • 什么是初始化属性 在声明属性的同时直接给属性进行初始化。 public IEnumerable<Score> MyScores { get; set; } = new HashSet<Score>(); 若当一个类的属性是引用类型时,我们必须要先初始化该引用类型...

    什么是初始化属性

    在声明属性的同时直接给属性进行初始化。

    public IEnumerable<Score> MyScores { get; set; } = new HashSet<Score>();
    

    若当一个类的属性是引用类型时,我们必须要先初始化该引用类型,才可以操作该类型。
    比如:

    public class User
    {
    
        public int Id { get; set; }
    
        public ICollection<Score> Scores { get; set; }
    }
    
    public class Score
    {
        public int Mark { get; set; }
    }
    

    我有了两个类型,其中,User 类中有一个 Scores 属性是类 Score 导航属性。

    当我们需要使用到 Scores 属性时,你可以有以下几种方式:
    1、显示地手动实例化:

    var user = new User();
    user.Scores = new List<Score>(); //手动的 new 一次
    user.Scores.Add(new Score { Mark = 100 });
    

    当然,这样很麻烦,因为每一次都需要自己去实例化,保不齐忘记了就抛异常了。

    2、在构造方法里实例化:

    public User()
    {
        this.Scores = new HashSet<Score>();
    }
    

    因此,当我 new User() 时,就会执行构造方法,因此 Scores 也会跟着实例化了,所以我不用担心使用的时候有没有被实例化。这种方法应该被经常推荐使用

    3、直接初始化属性

    public ICollection<Score> Scores { get; set; } = new HashSet<Score>();
    

    如果这样使用,就不需要在构造方法里再去实例化了,当然更方便。

    那初始化属性和构造方法实例化的区别是什么?

    既然构造方法里都能实例化了,那为什么还弄一个初始化属性呢?

    这就需要去了解他们的执行顺序了。用简单的 debugger 来直观的表示。

    public class User
    {
        public User()
        {
            this.Scores = new HashSet<Score>();
        }
    
        public int Id { get; set; }
    
        public ICollection<Score> Scores { get; set; }
    
        public IEnumerable<Score> MyScores { get; set; } = new HashSet<Score>();
    }
    

    改造一下这个 User 类,声明了两个属性都是 Score 类型的导航属性,一个用了构造方法去实例化,一个使用初始化属性来实例化。

    然后我们开始调试:
    在这里插入图片描述
    首先进入了断点,因为还没有实例化 User , 所以 user 对象是 null

    然后按了 F11,进入逐步调试
    在这里插入图片描述
    你会惊奇地发现,程序先走了初始化属性这一步;

    在这里插入图片描述
    这个时候,才开始进入构造方法里,但是这时,初始化属性的 MyScores 对象已经可以被使用了,但由于构造方法还没有执行,因此 Scores 对象还是 null

    在这里插入图片描述
    当构造方法执行完毕,Scores 对象也被实例化。

    因此我们得出了一个结论:初始化属性优先于构造方法

    这都是一瞬间的事情,基本上没什么区别吧?

    想一个场景,如果你需要在构造方法里做逻辑判断的时候,你就很有用了。

    public User()
    {
       if (MyScores == null)
       {
           this.Scores = new HashSet<Score>();
       }
    }
    

    当然,了解了执行顺序,就看你需要在什么样的场景去做使用。

    展开全文
  • 继续随着核心类的初始化展开探索其他的模块,这一篇来研究一下Vue的状态初始化。这里的状态初始化指的就是在创建实例的时候,在配置对象里定义的属性、数据变量、方法等是如何进行初始处理的。由于随后的数据更新...
  • 传统蓝牙初始化介绍 估计这个小节开始你就会对蓝牙协议栈有一点感觉了,感觉好像也没有那么困难,这个小节我们来进行初始化的讲解,完成这个小节后,你就惊奇的发现蓝牙设备竟然能被搜索到了· 笔者自己也摸索出了一...

    一. 声明

    本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下:

    第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。

    第二篇:Transport层介绍,主要介绍蓝牙协议栈跟蓝牙芯片之前的硬件传输协议,比如基于UART的H4,H5,BCSP,基于USB的H2等

    第三篇:传统蓝牙controller介绍,主要介绍传统蓝牙芯片的介绍,包括射频层(RF),基带层(baseband),链路管理层(LMP)等

    第四篇:传统蓝牙host介绍,主要介绍传统蓝牙的协议栈,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的协议吧。

    第五篇:低功耗蓝牙controller介绍,主要介绍低功耗蓝牙芯片,包括物理层(PHY),链路层(LL)

    第六篇:低功耗蓝牙host介绍,低功耗蓝牙协议栈的介绍,包括HCI,L2CAP,ATT,GATT,SM等

    第七篇:蓝牙芯片介绍,主要介绍一些蓝牙芯片的初始化流程,基于HCI vendor command的扩展

    第八篇:附录,主要介绍以上常用名词的介绍以及一些特殊流程的介绍等。

    另外,开发板如下所示,对于想学习蓝牙协议栈的最好人手一套。以便更好的学习蓝牙协议栈,相信我,学完这一套视频你将拥有修改任何协议栈的能力(比如Linux下的bluez,Android下的bluedroid)。

    ------------------------------------------------------------------------------------------------------------------------------------------

    CSDN学院链接(进入选择你想要学习的课程):https://edu.csdn.net/lecturer/5352?spm=1002.2001.3001.4144

    蓝牙交流扣扣群:970324688

    Github代码:https://github.com/sj15712795029/bluetooth_stack

    入手开发板:https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22329603896.18.5aeb41f973iStr&id=622836061708

    ------------------------------------------------------------------------------------------------------------------------------------------

    二.传统蓝牙初始化介绍

    估计这个小节开始你就会对蓝牙协议栈有一点感觉了,感觉好像也没有那么困难,这个小节我们来进行初始化的讲解,完成这个小节后,你就惊奇的发现蓝牙设备竟然能被搜索到了·

    笔者自己也摸索出了一个不写一行代码,就能把蓝牙芯片弄到被搜索到的方法,那么就让我们开始本小节吧(以CSR8X11蓝牙芯片为例,如果是不同的芯片,那么HCI vendor command部分会有所不同,我们会在后续说明更多的蓝牙芯片的vendor command)!

    每个蓝牙协议栈初始化command的顺序略有不同,这些是无所谓的·以我们的蓝牙协议栈抓的Snoop为例,整个步骤如下

    总结起来如下:

    1)首先保证硬件连接正常,这点没有什么好说的,你们就当作废话吧,哈哈,但是我还是要提两点注意事项:

    *Transport对应的硬件接线:如果是走H4的transport,那么蓝牙芯片的TX/RX/CTS/RTS需要分别接到MCU的RX/TX/RTS/CTS,如果是H5跟BCSP的话,那么只接TX/RX就行了(注意此部分接线方式有的芯片有特殊要求,那么会有所变动),如果是H2,那么没啥好讲的,插到USB口就行了,SDIO同理

    *蓝牙Enable/Reset pin,就是硬件使能蓝牙芯片

    2)对应Transport驱动(UART/USB/SDIO等)的初始化

    3)持续发送HCI_RESET直到芯片回应,接收到command complete with command opcode

    4)发送Vendor command,那么什么是vendor command呢,就是芯片原厂自己扩展的HCI command,来设定芯片的一些行为,比如CSR的叫做BCCMD/PSKEY,TI的叫做BTS,BCM的叫做HCD等,我们在后续详细介绍这些

    ---------------------------------------------------------------------------------------------------------------------------------

    从下面开始就是HCI core文档的command部分的使用了,每个协议栈定义的会有所不同,我的是最简化的。

    ---------------------------------------------------------------------------------------------------------------------------------

    5)发送Read Buffer Size command,接收到command complete with command opcode

    6)发送 Read BT address command,接收到command complete with command opcode.

    7)发送 Write code command,接收到command complete with comand opcode.

    8)发送 Change Local Name command,接收到command complete with comand opcode.

    9)发送 Write page timeout command,接收到command complete with comand opcode.

    10)发送 Write set Event Mask command,接收到command complete with comand opcode.

    11)发送 Write Write Simple Pairing command,接收到command complete with comand

    12)发送Write Scan Enable command,接收到command complete with comand opcode.

    下面我们就步骤来详细说下:

    Step 1)保证硬件连接正常

    Step 2)对应Transport驱动(UART/USB/SDIO等)的初始化

    我们以UART,Transport H4为例,首先看下STM32F103的UART初始化

    /******************************************************************************
     * func name   : hw_uart_bt_init
     * para        : baud_rate(IN)  --> Baud rate of uart1
     * return      : hw_uart_bt_init result
     * description : Initialization of USART2.PA0->CTS PA1->RTS PA2->TX PA3->RX
    ******************************************************************************/
    uint8_t hw_uart_bt_init(uint32_t baud_rate,uint8_t reconfig)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
    
        if(reconfig == 0)
            ringbuffer_init(&bt_ring_buf,bt_rx_buf,BT_RX_BUF_SIZE);
        /* Enable USART2,GPIOA,DMA1 RCC clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    
        USART_DeInit(USART2);
        USART_Cmd(USART2, DISABLE);
        /* Initialize the GPIOA0,GPIOA1,GPIOA2,GPIOA3 */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
        /* Data format :1:8:1, no parity check, hardware flow control */
        USART_InitStructure.USART_BaudRate = baud_rate;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;
        USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    
        /* Enable USART interrupts, mainly for idle interrupts */
        NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=BT_PREE_PRIO;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = BT_SUB_PRIO;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    
        /* Initializes USART2 to enable USART,USART idle interrupts, and USART RX DMA */
        USART_Init(USART2, &USART_InitStructure);
        USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
        USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
        USART_Cmd(USART2, ENABLE);
    
        /* Initializes DMA and enables it */
        hw_memset(&DMA_UART2,0,sizeof(DMA_InitTypeDef));
        DMA_DeInit(DMA1_Channel6);
        DMA_UART2.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;
        DMA_UART2.DMA_MemoryBaseAddr = (uint32_t)bt_dma_rx_buf;
        DMA_UART2.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_UART2.DMA_BufferSize = BT_DMA_BUF_SIZE;
        DMA_UART2.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_UART2.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_UART2.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_UART2.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_UART2.DMA_Mode = DMA_Mode_Normal;
        DMA_UART2.DMA_Priority = DMA_Priority_Medium;
        DMA_UART2.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel6, &DMA_UART2);
    
        DMA_Cmd(DMA1_Channel6, ENABLE);
    
        return BT_ERR_OK;
    
    }
    

    下面我们以Linux UART Transport H4为例

    
    
    uint8_t hw_uart_bt_init(uint32_t baud_rate,uint8_t reconfig)
    {
        speed_t baudrate;
        int flags = O_RDWR | O_NOCTTY;
    
        struct termios toptions;
        if(baud_rate == 115200)
            baudrate =  B115200;
        else
            baudrate =  B921600;
        if(reconfig == 0)
        {
            ringbuffer_init(&bt_ring_buf,bt_rx_buf,BT_RX_BUF_SIZE);
        }
    
        printf("phybusif_open /dev/ttyUSB0\n");
    
        uart_if.phyuart_fd = open("/dev/ttyUSB0", flags);
        if (uart_if.phyuart_fd == -1)
        {
            printf("ERROR:Unable to open port /dev/ttyUSB0\n");
            return -1;
        }
    
        printf("uart_if.phyuart_fd %d\n",uart_if.phyuart_fd);
        if (tcgetattr(uart_if.phyuart_fd, &toptions) < 0)
        {
            printf("ERROR:Couldn't get term attributes\n");
            return -1;
        }
    
        cfmakeraw(&toptions);
    
        // 8N1
        toptions.c_cflag &= ~CSTOPB;
        toptions.c_cflag |= CS8;
    
        toptions.c_cflag |= CREAD | CLOCAL | CRTSCTS;
        toptions.c_iflag &= ~(IXON | IXOFF | IXANY);
        toptions.c_cflag &= ~PARENB;
    
        toptions.c_cc[VMIN]  = 1;
        toptions.c_cc[VTIME] = 0;
    
        if(tcsetattr(uart_if.phyuart_fd, TCSANOW, &toptions) < 0)
        {
            printf("ERROR:Couldn't set term attributes\n");
            return -1;
        }
    
        if (tcgetattr(uart_if.phyuart_fd, &toptions) < 0)
        {
            printf("ERROR:Couldn't get term attributes\n");
            return -1;
        }
        cfsetospeed(&toptions, baudrate);
        cfsetispeed(&toptions, baudrate);
    
    
        if( tcsetattr(uart_if.phyuart_fd, TCSANOW, &toptions) < 0)
        {
            printf("ERROR:Couldn't set term attributes\n");
            return -1;
        }
    
        return BT_ERR_OK;
    
    }
    

    Step 3)发送HCI Reset以及回应,HCI reset格式如下

    什么参数都没有,我们来直接看下Wireshark直接抓的btsnoop

    回应如下:

    Step 4)发送Vendor command

    我们在这里先不具体讲vendor command,只是先列出CSR8X11 vendor command的raw data

    /*************************************************************************************************
    HCI command  PACKETS Format:
    	opcode 16 bit
    	para total len 8 bit
    	para 0
    **************************************************************************************************/
    
    /*************************************************************************************************
    BCCMD PACKETS Format:
               |	  type   |	length   |	seqno   |		varid	|	status   |	payload···	|
     uint 16   |	    1    |       2     |      3     |       4       |     5      |        6~        |
    **************************************************************************************************/
    
    /*************************************************************************************************
    BCCMD PS PACKETS Format:
               |	  header  |	key   |	length    |	stores      |		ps value  	|
     uint 16   |	    1-5   |    6    |      7     |       8        |      9~           |
    **************************************************************************************************/
    // minimal CSR init script to configure PSKEYs and activate them
    uint8_t csr8x11_initscript[] =
    {
        //  Set PSKEY_DEEP_SLEEP_STATE never deep sleep
        0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x02, 0x00, 0x03, 0x70, 0x00, 0x00, 0x29, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
    
        //  Set ANA_Freq to 26MHz
        0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x03, 0x00, 0x03, 0x70, 0x00, 0x00, 0xfe, 0x01, 0x01, 0x00, 0x08, 0x00, 0x90, 0x65,
    
        //  Set CSR_PSKEY_ANA_FTRIM 0x24 for csr8811
        0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x04, 0x00, 0x03, 0x70, 0x00, 0x00, 0xf6, 0x01, 0x01, 0x00, 0x08, 0x00, 0x24, 0x00,
    
        // Set CSR_PSKEY_DEFAULT_TRANSMIT_POWER 0x4
        0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x05, 0x00, 0x03, 0x70, 0x00, 0x00, 0x21, 0x00, 0x01, 0x00, 0x08, 0x00, 0x04, 0x00,
    
        // Set CSR_PSKEY_MAXIMUM_TRANSMIT_POWER 0x4
        0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00, 0x03, 0x70, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00, 0x08, 0x00, 0x04, 0x00,
    
        // Set CSR_PSKEY_BLE_DEFAULT_TRANSMIT_POWER 0x4
        0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x07, 0x00, 0x03, 0x70, 0x00, 0x00, 0xc8, 0x22, 0x01, 0x00, 0x08, 0x00, 0x04, 0x00,
    
        // Set CSR_PSKEY_BDADDR
        0x19, 0xc2, 0x02, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x03, 0x70, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x08, 0x00, 0x20, 0x00, 0x99, 0x1a, 0x86, 0x00, 0x1d, 0x00,
    
        // Set CSR_PSKEY_PCM_CONFIG32
        0x15, 0xc2, 0x02, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x70, 0x00, 0x00, 0xb3, 0x01, 0x02, 0x00, 0x08, 0x00, 0x80, 0x08, 0x80, 0x18,
    
        // Set CSR_PSKEY_PCM_FORMAT 0x60
        0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x03, 0x70, 0x00, 0x00, 0xb6, 0x01, 0x01, 0x00, 0x08, 0x00, 0x60, 0x00,
    
        // Set CSR_PSKEY_USER_LOW_JITTER_MODE
        0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x0b, 0x00, 0x03, 0x70, 0x00, 0x00, 0xc9, 0x23, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
    
        //  Set HCI_NOP_DISABLE
        0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x0c, 0x00, 0x03, 0x70, 0x00, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
    
        // Set UART baudrate to 921600
        0x15, 0xc2, 0x02, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x70, 0x00, 0x00, 0xea, 0x01, 0x02, 0x00, 0x08, 0x00,0x0e,0x00,0x00,0x10,/*0x1b, 0x00, 0x40, 0x77,*/
    
        //  WarmReset
        0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    };

    Step 5)发送Read Buffer Size command,接收到command complete with command opcode

    下面看下Read Buffer Size command(OGF=0x04)的封包格式

    抓取Wireshark btsnoop如下:

    回应如下:

    Sep 6)发送 Read BT address command,接收到command complete with command opcode.

    下面看下Read BT address command(OGF=0x04)的封包格式

    抓取Wireshark btsnoop如下:

    回应如下:

    Step 7)发送 Write code command,接收到command complete with comand opcode.

    下面看下Write cod command(OGF=0x04)的封包格式

    抓取Wireshark btsnoop如下:

    回应如下:

    Step 8)发送 Change Local Name command,接收到command complete with comand opcode.

    下面看下Change Local Name command(OGF=0x03)的封包格式

    参数这个地方有点特别,特别贴下,不管你的名字是多长的参数,比如叫做Wireless_link,但是都要凑够248byte,这是SIG的core文档定义,但是有一点,我自己试验过,不用248byte也行,但是最好还是按照SIG规范来,这个CSR8311芯片没有问题不代表其他芯片就可以。

    抓取Wireshark btsnoop如下:

    回应如下:

    Step 9)发送 Write page timeout command,接收到command complete with comand opcode.

    下面看下Write page timeout command(OGF=0x03)的封包格式

    参数如下:

    抓取Wireshark btsnoop如下:

    回应如下:

    Step 10)发送Set Event Mask,接收到command complete with comand opcode.

    下面看下Set Event Mask(OGF=0x03)的封包格式

    参数:

    Event_Mask:芯片产生的时间掩码

    抓取Wireshark封包:

    回应如下:

    Step 11)发送Write Simple Pairing command,接收到command complete with comand opcode.

    下面看下Write Simple Pairing(OGF=0x03)的封包格式

    参数:

    Simple_Pairing_mode:设置SSP的参数

    抓取Wireshark封包:

    回应如下:

    此部分代码配置在bt_conf.h中

    /***********   bluetooth function option **************************************/
    /** BT_PBUF_TRANSPORT_H2 = 0x01,BT_PBUF_TRANSPORT_H4 = 0x02,BT_PBUF_TRANSPORT_H5 = 0x03,BT_PBUF_TRANSPORT_BCSP = 0x04,*/
    #define BT_ENABLE_SNOOP 1
    #define BT_TRANSPORT_TYPE 0x02
    #define BT_ENABLE_SSP 0   /************这个地方配置SSP********************/
    /* IO_CAP_DISPLAY_ONLY->0x00 IO_CAP_DISPLAY_YES_NO->0x01 IO_CAP_KEYBOARD_ONLY->0x02 IO_CAP_NOINPUT_OUTPUT->0x03 */
    #define BT_SSP_IOCAP_CONF 3
    #define BT_CLASS_OF_DEVICE 0x200408;
    #define BT_LOCAL_NAME "BT_DEMO"
    #define BT_PIN_CODE "0000"
    #define BT_TIMER_COUNT 64 /* TIMER COUNT */

    此部分如果配置为1,那么就默认SSP配对,如果是0,那么就是PINCODE配对

    Step 12)发送Write Scan Enable command,接收到command complete with comand opcode.

    下面看下Write Scan enablecommand(OGF=0x03)的封包格式

    参数如下:

    抓取Wireshark btsnoop如下:

    回应如下:

    讲到这里蓝牙协议栈的初始化基本就完成了·,但是每个芯片的vendor command部分稍微有差异(也就是Step 4),后续我们再慢慢扩展更多的芯片,谢谢大家

    展开全文
  • 如何初始化一个vue项目

    千次阅读 2019-06-24 17:10:06
    使用vue-cli初始化项目 vue init webpack project-name (vue init是vue-cli的命令,webpack是项目使用的模板模型,project-name是项目名称) 之后根据自己项目所需进行enter操作 vue安装jQuery npm i ...
  • Kotlin实例初始化时,构造函数、成员变量、init块等的初始化顺序必须清楚,否则容易出bug: Example: open class Parent { private val a = println("Parent.a") constructor(arg: Unit=println("Parent ...
  • 数据库重新初始化步骤

    千次阅读 2019-11-29 10:09:37
    数据库重新初始化步骤数据库重新初始化步骤 数据库重新初始化步骤 重新初始化并恢复数据库 步骤: 1、停服务 vmserver.sh stopall 2、新建数据库目录并授权 cd /mnt/syncdata/pgsql mkdir -p data_new chown -R...
  • STM8 UART初始化+printf

    千次阅读 2018-10-08 22:39:19
    UART初始化: void Uart3_Initialize(void) {  UART3_Init(115200,UART3_WORDLENGTH_8D,UART3_STOPBITS_1,UART3_PARITY_NO,UART3_MODE_TXRX_ENABLE);  UART3_ITConfig(UART3_IT_RXNE_OR,ENABLE);  UART3_Cmd(E...
  • App的初始化思路

    2019-04-13 21:07:11
    1、在Example这个类中进行初始化,但是初始化的具体操作不是在这个类里面,要是都在这个类里面的话,代码量太多了,而是具体写一个对外的工具类Latte,在这个类里面进行具体的初始化操作。而这个Latte类只是写了...
  • 如何初始化数据库表

    千次阅读 2019-12-06 15:13:35
    TRUNCATE TABLE work_schedule # TRUNCATE TABLE 命令用于删除现有数据表中的所有数据(表初始化) TRUNCATE TABLE (表初始化)和delete table的区别 清空mysql表中的记录有以下两种方法: 1、delete from 表名;...
  • 有段javascript代码很困惑,经过不断的查资料,终于懂了!呵呵!
  • SD卡初始化步骤详解

    千次阅读 2016-12-15 14:55:29
    这里先从sd卡的初始化说起吧,只说初始化流程以及一些细节问题(spi模式)。 1、第一步,在将spi模块初始化好之后,将spi速度设为低速模式,我这里用的是250k 2、保持select脚为高电平,并向SD卡发送不低于74...
  • 为了清楚模板和数据如何渲染成最终的 DOM,所以各种初始化逻辑我们先不看。在初始化的最后,检测到如果有 el 属性,则调用 vm.$mount 方法挂载 vm,挂载的目标就是把模板渲染成最终的 DOM,下一节我们来分析 Vue ...
  • 一、数组初始化 数组只是相同类型的、用一个标识符名称封装到一起的对象序列或基本类型数据序列。数组是通过方括号下标操作符[]来定义和使用的。要定义一个数组,只需在类型名后加上一对空方括号即可: int[] a1...
  • string的几种初始化方法

    千次阅读 2020-04-20 18:05:50
    string: string的若干初始化方法2008年12月12日 星期五 11:12c++字符串(string)若干初始化的方法: string test1; //空串 string test2 = "内容"; //使用= string test3("内容"); //使用引用字符数组作为参数...
  • c++中变量未初始化的隐患

    千次阅读 2018-03-06 15:42:08
    变量未初始化是C++编程中最为常见和易犯的错误之一。但是对于全局变量,我们可以不进行初始化,这个变量会默认的用零进行初始化,但是这通常不是一个好的习惯。我们今天先不探讨全局变量还是静态全局变量。那么对于...
  • 标准初始化 标准均匀初始化 stand_uniform Wi,j∼gain ∗(−1fanin,1fanin)W_{i,j} \sim gain\ * (-\sqrt{\frac{1}{fan_in}},\sqrt{\frac{1}{fan_in}})Wi,j​∼gain ∗(−fani​n1​ ​,fani​n1​ ​) 标准正态...
  • 嵌入式系统初始化过程

    千次阅读 2018-08-14 20:08:58
    系统初始化过程可以分为 3 个主要环节,按照自底向上、从硬件到软件的次序依次为:片级初始化、板级初始化和系统级初始化。 转载:https://blog.csdn.net/jinmie0193/article/details/80393926 1.片级初始化  ...
  • 最近在一个4X4X4光立方,很好奇为啥淘宝上的光立方不用给IO口接上拉电阻也能这么亮。百度了一下才发现原来现在51的性能已经这么强了。其中IO口模式就有四种 那怎么分别初始化为这四种模式呢,简单示例如下: ...
  • [C/C++]构造函数初始化

    2020-03-29 20:08:52
    构造函数也是一样的,构造函数的最重要的功能,就是初始化,所有和初始化有关的,都可以放在构造函数中,比如类内部成员的初始化等。 ②初始化方式:其实有三种方式初始化: (1)在声明成员变量的时候直接初始化...
  • gorm初始化

    千次阅读 2019-06-03 17:19:09
    最近在想给这个小站增加点赞和评论功能,第三方系统又有各种限制,就想自己个后端,实现类似的功能,对于个人来说,数据量不是很大,单机的 mysql 足够存下所有数据,mysql 作为底层存储是个不错的选择 ...
  • 基于FPGA OV7670摄像头初始化配置

    千次阅读 2020-09-25 17:33:46
    目录 一、OV7670摄像头简介 二、ov7670 SCCB协议简介 三、OV7670初始化寄存器配置 四、OV7670初始化代码编写 1、初始化过程 2、RTL设计 五、仿真测试 一、OV7670摄像头简介 OV7670/OV7171 图像传感器,体积小、工作...
  • 为了方便初期系统开发,Dallas Semiconductor公司提供了C风格范例代码,它可以在T1或E1模式下初始化设备,软件开发人员只需针对所需的操作修改代码,或编写与特定系统相关的功能。一旦代码编译完毕,即可载入系统...
  • Java数组初始化

    千次阅读 2019-05-06 22:34:32
    1.Java数组初始化的两种方法: 静态初始化:程序员在初始化数组时为数组每个元素赋值; 动态初始化:数组初始化时,程序员只指定数组的长度,由系统为每个元素赋初值。 Java数组是一种引用数据类型。数组...
  • java报错,无法初始化主类

    万次阅读 2018-10-05 11:04:08
    错误: 无法初始化主类 Demo 原因: java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Workbook 请问大佬们这个怎么 代码如下: import java.io.FileOutputStream; import java.io.IOException; ...
  • 没有躲过的坑--程序中的变量未初始化

    万次阅读 多人点赞 2015-11-21 14:44:17
    变量未初始化是C++编程中最为常见和易犯的错误之一。但是对于全局变量,我们可以不进行初始化,这个变量会默认的用零进行初始化,但是这通常不是一个好的习惯。我们今天先不探讨全局变量还是静态全局变量。那么对于...
  • 虚拟机的初始化配置

    千次阅读 2018-07-17 11:01:15
    1、安装虚拟机 :自行百度(省略。。。。) 2、配置虚拟机,(网络适配器选择桥接模式,后期可以上网、、,如果是虚拟出来的虚拟机的话,CD/DVD:配置的时候选择 使用ISO映射文件) 3、配置 vi /etc/sysconfig/...
  • 神经网络权重初始化问题

    万次阅读 2017-09-01 12:24:26
    之前看Andrew大神的视频有介绍到神经网络权重需要随机初始化而不是全初始化为0的问题,其真正深层次的含义没有明白,所以结合一些资料(cs231n课程)希望能让自己之后再想到这个问题的时候能够快速地明白过来。...
  • 作为一个经常使用Spring的后端程序员,小编很早就想...不过,男儿在世当立志,今天就先从Spring IOC容器的初始化开始说起,即使完成不了对整个Spring框架的完全掌握,也不丢人,因为小编动手了,稳住,咱能赢! 下...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 114,499
精华内容 45,799
关键字:

初始化怎么弄