一、懂单片机时序图

单片机是通过什么样的办法进行取指令,执行指令和其它操作的呢?

    在这里引入了一个时序的概念。

时钟电路

    单片机时钟电路有三种方式:

    1、单片机内部有一个用于构成振荡器的高增益反相放大器,引脚XTAL1和XTAL2分别是此放大器的输入端和输出端,XTAL1和XTAL2需外接上晶体和合适的电容。  

    2、有的单片机内部也自带时钟电路,用于产生时钟信号。

    3、单片机管脚XTAL2直接接晶振。

周期

1 时钟周期

    时钟电路产生时钟信号的周期我们叫时钟周期(振荡周期)。

    单片机通电后就产生了固定标称值的脉冲信号,单片机就是在脉冲信号的驱动下顺序地从ROM中(程序存储器)取出指令一条一条的顺序执行,然后进行一系列的微操作控制,来完成各种指定的动作。

2 机器周期

    单片机每访问一次存储器的时间我们把它称为一个机器周期,它是一个时间基准就象我们日常生活中使用的秒一样。单片机中一个机器周期包括12个振荡周期。振荡周期就是振荡源的周期也就是我们使用的晶振的时间周期。一个12M的晶振它的时间周期是1/12微秒,那么使用12M晶振的单片机它的一个机器周期就应该等于12*1/12微秒,也就是1微秒。

3 指令周期

    单片机中有些指令只要一个机器周期而有些指令则需要两个或三个机器周期另外还有两条指令需要4个机器周期。如何衡量指令执行时间的长短我们就要用到一个新的概念:指令周期,即执行一条指令所需的机器周期。

时序

    对于芯片开发使用来说,时序图是较为核心也较为重要的一个知识点。在厂家给出的芯片数据手册中,时序图也是非常重要的参数细节。开发者拿到一款芯片时,首先需要做的就是阅读其数据手册,对上面的内容进行提取和掌握。因此能够顺利的阅读并了解到单片机时序图想要传达的意思是非常关键的。

    单片机时序是指单片机执行指令时应发出的控制信号的时间序列。这些控制信号在时间上的相互关系就是CPU的时序。它是一系列具有时间顺序的脉冲信号。

    CPU发出的时序有两类:一类用于片内各功能部件的控制,它们是芯片设计师关注的问题,对用户没有什么意义。另一类用于片外存储器或I/O端口的控制,需要通过器件的控制引脚送到片外,这部分时序对分析硬件电路的原理至关重要,也是软件编程遵循的原则,需要认真掌握。

    CPU发出的时序有两类:一类用于片内各功能部件的控制,它们是芯片设计师关注的问题,对用户没有什么意义。另一类用于单片机外部芯片的控制,这部分时序对分析硬件电路的原理至关重要,也是软件编程遵循的原则。

    操作时序永远使用是任何一片IC芯片的最主要的内容。一个芯片的所有使用细节都会在它的官方器件手册上包含。所以使用一个器件事情,要充分做好的第一件事就是要把它的器件手册上有用的内容提取,掌握其工作时序。

    在这里我们以液晶1602为例,分析其操作时序。其基本时序有读状态,写指令,读数据和写数据。

    为了方便大家理解,这里以1602为例进行讲解,1602的引脚是很整齐的SIP单列直插封装,所以器件手册只给出了引脚的功能数据表:

嵌入式分享合集130_嵌入式硬件

   这里,我们需要关注1602的几个管脚,分别是RS,RW,E,D0...D7。由上面的说明我们可以知道:

    RS:数据/命令(状态)选择端,当此脚为高电平时,可以对1602进行数据字节的传输操作,而此脚为低电平时,进行命令(状态)字节的传输操作。

    RW:读写选择端,当此脚为高电平可对LCD1602进行读数据操作,反之进行写数据操作。

    E:使能信号,其实是LCD1602的数据控制时钟信号,利用该信号的上升沿实现对LCD1602的数据传输。

    D0...D7:8位并行数据口。

    在此,我们分析两个写时序:写命令和写数据。

    1、当我们要写指令字,设置LCD1602的工作方式时:需要把RS置为低电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。

嵌入式分享合集130_嵌入式硬件_02

 2、当我们要写入数据字,在1602上实现显示时:需要把RS置为高电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。

嵌入式分享合集130_嵌入式硬件_03

  开发者只需要关注以下几个管脚:

    3脚:VL,液晶显示偏压信号,用于调整LCD1602的显示对比度,一般会外接电位器用以调整偏压信号,注意此脚电压为0时可以得到最强的对比度。

    4脚:RS,数据/命令选择端,当此脚为高电平时,可以对1602进行数据字节的传输操作,而此脚为低电平时,则是进行命令字节的传输操作。命令字节,即是用来对LCD1602的一些工作方式作设置的字节;数据字节,即使用以在1602上显示的字节。值得一提的是,LCD1602的数据是8位的。

    5脚:R/W,读写选择端。当此脚为高电平可对LCD1602进行读数据操作,反之进行写数据操作。笔者认为,此脚其实用处不大,直接接地永久置为低电平也不会影响其正常工作。但是尚未经过复杂系统验证,保留此意见。

    6脚:E,使能信号,其实是LCD1602的数据控制时钟信号,利用该信号的上升沿实现对LCD1602的数据传输。

    7~14脚:8位并行数据口,使得对LCD1602的数据读写大为方便。

LCD1602的操作时序

 

嵌入式分享合集130_嵌入式硬件_04

在此,可以先不读出它的数据的状态或者数据本身,所以只需要看两个写时序:

    ①当要写指令字,设置LCD1602的工作方式时:需要把RS置为低电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。

    ②当要写入数据字,在1602上实现显示时:需要把RS置为高电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。

    实际上写指令和写数据,差别仅仅在于RS的电平不一样而已。以下是LCD1602的时序图:

 

嵌入式分享合集130_嵌入式硬件_05

只要慢慢学会看时序图,要知道操作一个器件的精华便蕴藏在其中,看懂看准了时序,再操控这个芯片就是非常容易的事了。这里使用1602作为例子主要是因为1602的时序是目前最简单的时序之一。

    看时序图需要注意的问题:

    1、注意时间轴,从左往右的方向为时间正向轴,即时间在增长。

    2、时序图最左边一般是某一根引脚的标识,表示此行图线体现该引脚的变化,上图分别标明了RS、R/W、E、DB0~DB7四类引脚的时序变化。

    3、有线交叉状的部分,表示电平在变化。

    4、两条平行线分别对应高低电平,如上图右上角所示。

    5、密封的菱形部分,表示数据有效,Valid Data这个词也显示了这点。

    6、时序图里各个引脚的电平变化,基于的时间轴是一致的。一定要严格按照时间轴的增长方向来精确地观察时序图。要让器件严格的遵守时序图的变化。

    7、时间的标注,也是个十分重要的信息,这些时间的标注表明了某些状态所要维持的最短或最长时间。因为器件的工作速度也是有限的,一般都跟不上主控芯片的速度,所以它们直接之间要有时序配合。下面是时序参数表:

    需要十分严重注意的是,时序图里各个引脚的电平变化,基于的时间轴是一致的,一定要严格按照时间轴的增长方向来精确地观察时序图,要让器件严格的遵守时序图的变化,在类似于18B20这样的单总线器件对此要求尤为严格。

时间标注:

    细心的朋友或许注意到了文中关于时间的标注,这也是个十分重要的信息,这些时间的标注表明了某些状态所要维持的最短或最长时间。因为器件的工作速度也是有限的,一般都跟不上主控芯片的速度,所以它们直接之间要有时序配合。下面是时序参数表:

    开发者要注意估计主控芯片的指令时间,可以在官方数据手册上查到MCU的一些级别参数。比如现在用AVRM16做为主控芯片,外部12MHz晶振,(1/12MHz)s是振荡周期,而不是时钟周期,因为时钟周期(状态周期)等于两个振荡周期,换句话说就是对振动频率进行“二分频”的振荡信号,所以(2/12MHz)s才是晶振为12MHz时的时钟周期。

    以上给的时间参数全部是ns级别的,所以即便在程序里不加延时程序,也应该可以很好的配合LCD1602的时序要求了。怎么看这个表呢?很简单,在时序图里可以找到TR1,对应时序参数表,可以查到这个是E上升沿/下降沿时间,最大值为25ns,表示E引脚上的电平变化,必须在最大为25ns之内的时间完成。

    以上介绍的这些内容,虽然是以LCD1602为例,但这仅仅是为了帮助大家进行理解,其中提到的参数是大部分单片机都会有的,因此大家可以通过本文中给予的解读方式来套用到其他单片机当中,大部分的单片机时序图都会遵循文中给出的规则,当大家渐渐掌握其中的内容后,就可以发现其实看懂单片机的时序图其实并不难。

    现在我来解读我对这个时序图的理解:

    当要写命令字节的时候,时间由左往右,RS变为低电平,R/W变为低电平,注意看是RS的状态先变化完成。然后这时,DB0~DB7上数据进入有效阶段,接着E引脚有一个整脉冲的跳变,接着要维持时间最小值为tpw=400ns的E脉冲宽度。然后E引脚负跳变,RS电平变化,R/W电平变化。这样便是一个完整的LCD1602写命令的时序。

 

 

二、STM32中数据类型定义

  stdint.h 这里放着C语言的标准表达方式

typedef   signed        char      int8_t; 
typedef   signed short  int       int16_t;
typedef   signed        int       int32_t;
typedef   signed      __int64     int64_t;
typedef unsigned           char       uint8_t;
typedef unsigned short     int        uint16_t;
typedef unsigned           int        uint32_t;
typedef unsigned         __int64      uint64_t;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

    stm32f10x.h 这个文件主要是为了兼容旧版本

typedef   uint32_t   u32;   ///32位
typedef   uint16_t   u16;   ///16位
typedef   uint8_t     u8;   ///8位
  • 1.
  • 2.
  • 3.

    u8 最大255 , u16最大65535 , 就这个意思u8 a=255 a+1=0  , u16 b=255 b+1=256

嵌入式分享合集130_数据_06

 

三、C语言~struct

定义结构体变量

    下面举一个例子来说明怎样定义结构体变量。

struct string 
 { 
    char name[8]; 
    int age; 
    char sex[2]; 
    char depart[20]; 
    float wage1, wage2, wage3, wage4, wage5; 
 }person;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

    这个例子定义了一个结构名为string的结构体变量person。还可以省略变量名person,做如下定义:

struct string 
 { 
    char name[8]; 
    int age; 
    char sex[2]; 
    char depart[20]; 
    float wage1, wage2, wage3, wage4, wage5; 
 };  
 struct string person;   //定义结构名为string的结构体变量person
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

    定义多个具有相同形式的结构变量:

struct string Liming, Liuqi, ...;
  • 1.

    有一种结构体常常出现在函数内部,省略结构名,则称之为无名结构,如下:

struct 
 { 
    char name[8]; 
    int age; 
    char sex[2]; 
    char depart[20]; 
    float wage1, wage2, wage3, wage4, wage5; 
 } Liming, Liuqi;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

结构体成员的获取与赋值

    结构是一个新的数据类型,结构成员的表示方式为:

结构变量.成员名
  • 1.

    如果将"结构变量.成员名"看成一个整体,这样就可以像其他变量那样使用。

    下面这个例子定义了一个结构变量stu1,分别给name、age、group赋值,并打印输出。

#include <stdio.h>
int main()
{
struct
  {
    char *name;  //姓名
int age;  //年龄
    char group;  //所在小组
  } stu1;
//给结构体成员赋值
  stu1.name = "Tom";
  stu1.age = 18;
  stu1.group = 'A';
//读取结构体成员的值
printf("%s的年龄是%d,在%c组\n", stu1.name, stu1.age, stu1.group);
return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

结构体数组

    结构体数组就是具有相同结构类型的变量集合,假如要定义一个班级40个同学 的姓名、性别、年龄和住址, 可以定义成一个结构数组。如下所示:

struct
 { 
    char name[8]; 
    char sex[2]; 
    int age; 
    char addr[40]; 
 }student[40];
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

    结构体数组成员的访问是以数组元素为结构变量的, 其形式为:

结构数组元素.成员名
  • 1.

    例如:

student[0].name
student[30].age
  • 1.
  • 2.

结构体指针

    结构体指针由一个加在结构变量名前的*操作符来定义,定义一个结构体指针如下:

struct string
{ 
   char name[8]; 
   char sex[2]; 
   int age; 
   char addr[40]; 
}*student;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

    使用结构体指针对结构体成员的访问与结构体变量对结构体成员的访问在表达方式不同。结构体指针对结构体成员的访问方式为:

结构体指针名->结构体成员
  • 1.

    给上面定义的结构体中name和age赋值的语句:

strcpy(student->name, "acket"); //student->name就是(*student).name
student->age=18;
  • 1.
  • 2.

    需要指出的是结构体指针是指向结构体的一个指针,即结构体中第一个成员的首地址,因此在使用之前应该对结构体指针初始化,即分配整个结构体长度的字节空间:

student=(struct string*)malloc(size of (struct string));
//size of (struct string)是自动求取string结构体的字节长度
  • 1.
  • 2.

    malloc()函数定义了一个大小为结构体长度的内存区域,然后将其地址作为结构体指针返回。

位结构

    位结构是一种特殊的结构体,位结构定义的一般形式为:

struct 位结构名
 { 
    数据类型 变量名: 整型常数; 
    数据类型 变量名: 整型常数; 
 }位结构变量;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

    其中数据类型必须是int(unsigned或signed,但当成员长度为1时, 会被认为是unsigned类型),整型常数必须是0~15的非负整数,表示二进制位个数。变量名是选择项,可以不命名,下面定义了一个位结构:

struct
 { 
    unsigned incon: 8;    /*incon占用低字节 的0~7共8位*/ 
    unsigned txcolor: 4;/*txcolor占用高字节的0~3位共4位*/ 
    unsigned bgcolor: 3;/*bgcolor占用高字节的4~6位共3位*/ 
    unsigned blink: 1;  /*blink占用高字节的第7位*/ 
 }ch;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

    位结构成员的访问与结构体成员的访问相同,访问位结构中的bgcolor成员可写成:

ch.bgcolor
  • 1.

举个例子

struct info
{ 
    char name[8]; 
    int age; 
    struct addr address; 
    float pay; 
    unsigned state: 1; 
    unsigned pay: 1; 
}workers;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

    上面结构体定义了工资的信息,其中有两个只有1位的位结构成员,表示工人的状态以及工资是否已发放。

typedef定义结构体

typedef struct  person
{
int age ;
char *name;
char *sex;
}student;
student stu1; //此处可以用student来定义一个结构体变量
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

    typedef的作用就相当于给struct person取了一个别名student。

四、PLC通讯-串口

串行端口是计算机上非常通用的设备通信协议(不要将其与通用串行总线或USB混淆)。大多数计算机包含两个基于RS232的串行端口。

1、PLC与计算机之间的通信:PLC与网络控制系统中的编程、监控、调试计算机或上位机之间的通信

2、PLC与通用外部设备的通信:PLC与具有通用通信接口的外部设备(如rs232rs422/485等)的通信。

嵌入式分享合集130_单片机_07