电子工作室培训(一)

电子工作室培训(一)

一、Keil For C51开发环境的搭建

1、下载Keil安装包及注册机压缩包

  • 编译器Keil5 for c51链接如下:
    链接:https://pan.baidu.com/s/1osO4K9HQlCS52o6RcJttDA
    提取码:JSU6
  • 注册机链接:https://pan.baidu.com/s/1Qaa_BYtrXsQsx6kaTmUnSw
    提取码:JSU6
  • STC-ISP下载工具连接:https://pan.baidu.com/s/1wNquPWFLCOjDJjiARw_PZw
    提取码:JSU6
    工作室同学请到QQ群下载。
    2、安装
    解压Keiluvision5C51版,找到安装程序C51-V957.exe,右键以管理员身份运行,按提示操作(该√的√上,该NEXT就NEXT)当出现如下界面,选择一个安装路径,建议在自己D盘根目录下,新建一个有辨识性的文件夹来作为软件安装路径(如这里在D盘新建keil5_c51)。
    在这里插入图片描述
    这里随便填在这里插入图片描述
    点NEXT,等待安装完成。可以在桌面上看到keil的图标,右键以管理员身份打开
    3,破解
    解压注册机压缩包:2020版keilCRACK.zip,打开程序:keygen.exe(此处友情提醒调小电脑的音量~),打开keil,按如下步骤打开License Management。
    在这里插入图片描述
    复制CID
    在这里插入图片描述
    转到注册机中,按如图操作
    在这里插入图片描述
    将注册机生成的License ,复制至keil的License Management中,如图:
    在这里插入图片描述
    完成之后,关闭keil重新打开,就可以开始你的编程之旅了。
    4、STC-ISP下载工具的使用
  • 下载压缩包:stc-isp-15xx-v6.87P.zip并解压。
  • 安装USB驱动程序:打开解压后文件夹下的USB to UART Driver文件夹,打开CH340_CH341,找到CH340_CH341.exe文件右键以管理员身份运行,点击安装
  • 在这里插入图片描述
  • 在解压后的文件夹里找到stc-isp-15xx-v6.87P.exe,双击就可以运行,不需要安装,可以右键选择发送到-发送到桌面快捷方式,这样就可以在桌面运行它啦。(也可以直接拖到桌面上)。
  • 至此,开发环境搭建成功。

二、常用C语法

参考菜鸟教程:https://www.runoob.com/cprogramming/c-tutorial.html

if-else
一般形式:

  • 一个 if 后可跟零个或一个 else,else 必须在所有 else if 之后。
  • 一个 if 后可跟零个或多个 else if,else if 必须在 else 之前。
  • 一旦某个 else if 匹配成功,其他的 else if 或 else 将不会被测试。
if(boolean_expression 1)
{
   /* 当布尔表达式 1 为真时执行 */
}
else if( boolean_expression 2)
{
   /* 当布尔表达式 2 为真时执行 */
}
else if( boolean_expression 3)
{
   /* 当布尔表达式 3 为真时执行 */
}
else 
{
   /* 当上面条件都不为真时执行 */
}

实例:当输入20,将输出:a 的值是 20

#include <stdio.h>
 
int main ()
{
   /* 局部变量定义 */
   int a = 100;
 
   /* 检查布尔条件 */
   if( a == 10 )
   {
       /* 如果 if 条件为真,则输出下面的语句 */
       printf("a 的值是 10\n" );
   }
   else if( a == 20 )
   {
       /* 如果 else if 条件为真,则输出下面的语句 */
       printf("a 的值是 20\n" );
   }
   else if( a == 30 )
   {
       /* 如果 else if 条件为真,则输出下面的语句 */
       printf("a 的值是 30\n" );
   }
   else
   {
       /* 如果上面条件都不为真,则输出下面的语句 */
       printf("没有匹配的值\n" );
   }
   printf("a 的准确值是 %d\n", a );
 
   return 0;
}

switch

  • 先计算switch表达式的值,再逐个和 case 后的常量表达式比较,若不等则继续往下比较,若一直不等,则执行 default 后的语句;若等于某一个常量表达式,则从这个表达式后的语句开始执行,并执行后面所有 case 后的语句。

  • 与 if 语句的不同:if 语句中若判断为真则只执行这个判断后的语句,执行完就跳出 if 语句,不会执行其他 if 语句;而 switch 语句不会在执行判断为真后的语句之后跳出循环,而是继续执行后面所有 case 语句。在每一 case 语句之后增加 break 语句,使每一次执行之后均可跳出 switch 语句,从而避免输出不应有的结果。
    switch语句一般形式:

switch(表达式)
{
    case 常量表达式1:语句1;
    case 常量表达式2:语句2;
    ...
    default:语句n+1;
}

例:输入1-12,输出对应的月份。

#include <stdio.h>

int main()
{
    int a;
    printf("input integer number: ");
    scanf("%d",&a);
    switch(a)
    {
        case 1:printf("Monday\n");
        break;
        case 2:printf("Tuesday\n");
        break;
        case 3:printf("Wednesday\n");
        break;
        case 4:printf("Thursday\n");
        break;
        case 5:printf("Friday\n");
        break;
        case 6:printf("Saturday\n");
        break;
        case 7:printf("Sunday\n");
        break;
        default:printf("error\n");
    }
}

for
一般形式:

for ( init; condition; increment )
{
   statement(s);
}

下面是 for 循环的控制流:

  • init 会首先被执行,且只会执行一次。这一步允许您声明并初始化任何循环控制变量。您也可以不在这里写任何语句,只要有一个分号出现即可。
  • 接下来,会判断 condition。如果为真,则执行循环主体。如果为假,则不执行循环主体,且控制流会- 跳转到紧接着 for 循环的下一条语句。
  • 在执行完 for 循环主体后,控制流会跳回上面的 increment 语句。该语句允许您更新循环控制变量。该语句可以留空,只要在条件后有一个分号出现即可。
  • 条件再次被判断。如果为真,则执行循环,这个过程会不断重复(循环主体,然后增加步值,再然后重新判断条件)。在条件变为假时,for 循环终止。
    实例:
#include <stdio.h>
 
int main ()
{
   /* for 循环执行 */
   for( int a = 10; a < 20; a = a + 1 )
   {
      printf("a 的值: %d\n", a);
   }
 
   return 0;
}

输出如下:

a 的值: 10
a 的值: 11
a 的值: 12
a 的值: 13
a 的值: 14
a 的值: 15
a 的值: 16
a 的值: 17
a 的值: 18
a 的值: 19

while
一般形式:

while(condition)
{
   statement(s);
}
  • 在这里,statement(s) 可以是一个单独的语句,也可以是几个语句组成的代码块。
  • condition 可以是任意的表达式,当为任意非零值时都为 true。当条件为 true 时执行循环。 当条件为 false 时,退出循环,程序流将继续执行紧接着循环的下一条语句。

实例:

#include <stdio.h>
 
int main ()
{
   /* 局部变量定义 */
   int a = 10;

   /* while 循环执行 */
   while( a < 20 )
   {
      printf("a 的值: %d\n", a);
      a++;
   }
 
   return 0;
}

运行结果:

a 的值: 10
a 的值: 11
a 的值: 12
a 的值: 13
a 的值: 14
a 的值: 15
a 的值: 16
a 的值: 17
a 的值: 18
a 的值: 19

do-while
一般形式:

do
{
   statement(s);

}while( condition );
  • 不像 for 和 while 循环,它们是在循环头部测试循环条件。在 C 语言中,do…while 循环是在循环的尾部检查它的条件。
  • do…while 循环与 while 循环类似,但是 do…while 循环会确保至少执行一次循环。

宏定义

  • C语言中,可以用 #define 定义一个标识符来表示一个常量。其特点是:定义的标识符不占内存,只是一个临时的符号,预编译后这个符号就不存在了。
  • 所谓的常量可以是各种数据类型,如:int、float、char等。
  • 可以理解为替换,编译器在编译前自动将标识符替换成代表的常量。
  • 后面不要加分号!
  • 宏定义最大的好处是“方便程序的修改”。使用宏定义可以用宏代替一个在程序中经常使用的常量。注意,是“经常”使用的。这样,当需要改变这个常量的值时,就不需要对整个程序一个一个进行修改,只需修改宏定义中的常量即可。且当常量比较长时,使用宏就可以用较短的有意义的标识符来代替它,这样编程的时候就会更方便,不容易出错。因此,宏定义的优点就是方便和易于维护。

一般形式:

#define  标识符  常量   //注意, 最后没有分号

实例:

#define  Days  30   

编译器会将所有出现Days的地方将其换为30。
函数
数组
指针
结构体
联合
枚举

以上内容由于时间关系,暂时不聊,请同学们自行了解。

2、数据类型

  • 我们在做单片机、嵌入式程序设计的时候,往往芯片内存资源十分有限,所以根据不同的数据选择合适的数据类型可以节约内存空间,提高程序的执行效率。
  • 需要注意数据类型所表示的数值范围,避免溢出,使程序运行错误。

*整型类型:

intcharunsignedsignedfloatdouble
*浮点型
在这里插入图片描述
*void型

  • void 类型指定没有可用的值。它通常用于以下三种情况下:
    在这里插入图片描述

*51单片机中特殊的数据类型:

应对51单片机硬件的一些特点,Keil 扩展了bit、sbit、sfr、sfr16等四种特殊基本数据类型,它们都是标准C中所没有的。其中:

  • bit:声明一个普通的位变量,值为0或1。例如:“bit flag;”
  • sbit:声明特殊功能寄存器中的某一位。例如,使用"sbit TI = P0^0;",就声明了TI为P0端口的第0位。(端口我们将马上介绍)
  • sfr:声明一个8位寄存器为特殊功能寄存器。例如,将51单片机内存地址0x98处的存储单元声明为8位特殊功能寄存器SCON,可以使用"sfr SCON = 0x98;"语句。
  • sfr16:声明一个16位的寄存器为特殊功能寄存器。为了将51单片机内存地址0xCC处开始的连续两个存储单元声明为一个统一的16位特殊功能寄存器T2,可以使用"sfr16 T2 = 0xCC;"语句。

注意:

  • 在Keil uVision中,用sbit、sfr、sfr16声明特殊功能寄存器变量或特殊功能寄存器位变量时,其声明语句都只能放在函数外,而不能放在函数内,否则出现语法错误。
  • 用bit声明普通位变量时,声明语句既可放在函数外,也可放在函数内。
  • bit、sbit、sfr、sfr16都不支持指针和数组扩展,因此,不能定义bit、sbit、sfr、sfr16型指针和数组。
  • 对于初学者来说,其实没有必要深究sbit、sfr、sfr16的用法,它们通常用在51单片机的系统自带头文件中,一般情况下无需用户关心。

三、数字逻辑及进制转换

1、数字逻辑

1、与(and)

  • 全为ture结果才为ture。
  • &——按位与。
    如:10&7=1010b&0111b=0010b=2;
  • &通常用来对某些位清0或保留某些位。
    如:有一个数为0110 1101b,希望保留低四位而把高4位清0。
    0110 1101b & 0000 1111b = 0000 1101b;
  • &&——逻辑与。
    如: (1>=0)&&(1>=2)=1&0=0;

2、或(or)

  • 只要一个为ture结果就为ture。
  • ‘|’——按位或
    如:6|2=0110b | 0010b = 0110b;
  • ‘||’逻辑或
    如: (1>=0)|| (1>=2)=1|0=1;

3、非(not)

  • ture to false——false to ture;
  • ‘~’——按位取反
    如:~(0000 1001)= 1111 0110
  • ‘~’也可进行单目运算
    如:~1=0;

4、异或

  • 不同为Ture,相同为false。
  • “^”——按位异或。双目运算符,其功能是参与运算的两数各对应的二进位相异或;当两对应的二进位相异时,结果为1。
    如:0000 1010 ^ 0000 0101 = 0000 1111;

5、移位

  • “<<”,左移,双目运算符,功能:把“<<”左边运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数。
  • 通俗来说,就是整串数左移,高位的不要,低位补0
    如:1111 1111 << 3 = 1111 1000;
    - “>>”右移,这里不赘述。

2、进制转换

这里不展开讲,请点击参考此文
1、十进制转二进制
2、八进制转二进制
3、十六进制转二进制
4、二进制转十进制
5、二进制转八进制
6、二进制转十六进制
因为单片机编程常需要二进制与十六进制转换,故讨论之。

  • “8421”法,每4位二进制对应应一位十六进制,其权对应分别为8、4、2、1。注意取4为二进制应从低位开始取,高位不足4位则高位补0即可。
    如:1111 1001b = (8+4+2+1)(8+0+0+1)h=F9h=0XF9;
    11 1011b = (0+0+2+1)(8+0+2+1) = 3BH = 0X3B;
    这里的h表示十六进制(hexadecimal),我们写C程序一般在数字前写0X为表示十六进制(注意:是零0,而不是英文o)
  • 这里的英文字符十六进制的a,b,c啊大小写都可以。如:0XFA = 0xfa;

3、单片机电平逻辑

  • 什么是电平:电平”就是指电路中两点或几点在相同阻抗下电量的相对比值。
  • 可以近似理解为电平为电压。但电平只有高低之分,对应的应该是一个电压范围。如:TTL电平中,+5V等价于逻辑"1",0V等价于逻辑"0"。我们单片机系统使用的就是TTL电平,但高电平取决于电源(VCC)的电压。
  • 我们使用的单片机中高电平代表“1”,低电平代表“0”。

四、什么是单片机?

  • 单片微型计算机( Single-Chip -Microcomputer),现在也称微控制器(Micro Controller Unit)简称MCU。
  • 它其实就是一种集成电路芯片,是通过超大规模集成电路技术,将CPU、RAM、ROM、输入输出和中断系统、定时器/计数器等功能,塞进一块硅片上,变成一个超小型的计算机。
  • 通俗的说,单片机就是一个芯片而已,只是我们可以通过对其编写程序,去控制它进行相应的工作。
  • 8051单片机:51单片机是对所有兼容Intel 8051指令系统的单片机的统称。 并不是指的某一特定型号的单片机,而是使用51内核单片机的统称。 8051是一种内核,其他公司基于此内核的基础上加入其他的外设开发出多种型号的"51单片机"。如:我们此次使用的是宏晶公司(STC)的STC15W4K58S4单片机。

STC官网:http://www.stcmcudata.com/

在这里插入图片描述
在这里插入图片描述

五、认识原理图

  • 原理仅表示电路连接关系,与具体的PCB的布局、布线并没有直接的关系
  • 我们需要从原理图中得到单片机与外围电路的连接,从而知道该如何写程序控制某一外设。
    在这里插入图片描述

六、新建一个keil工程

1、添加STC型号和头文件到keil中

  • 打开STC-ISP软件,按图操作
    在这里插入图片描述
  • 打开keil5,选择Project->New …如图:
    在这里插入图片描述
  • 选择工程保存路径,建议每一个工程建一个文件夹好方便管理,如我这里新建了一个51单片机的文件夹,用来保存51单片机的工程,建了一个LED的文件夹来保存我们这次的工程文件,之所以叫LED是因为我们此次培训内容为点亮一个LED,这样具有辨识性,方便你在某个夜深人静的时候想看点亮LED的代码能一下子就找到~~,然后点击保存。
    在这里插入图片描述
  • 选择单片机型号,我们可以在1那里的选择栏里面找到STC MCU Dtabase(默认不是这个),然后再2那里选择我们本次使用的芯片STC15W4K32S4。然后点击OK。其实,如果你的程序实现的功能是STC各种型号普遍都有的,你也可以随便选一个,比如我们此次点亮一个LED,仅仅就是控制单片机的一个IO(输入输出引脚)口,当然任意型号的都能满足要求,但建议养成选择对应型号单片机的习惯!
  • 如果你找不到STC的单片机,也就是前面的没有成功添加STC型号和头文件,这也没关系,可以在Search栏里面输入AT89C51来找到AT89C51然后选择也可以的。
    在这里插入图片描述
  • 之后会提示你是否复制51单片机的启动文件到工程中,这里我们选择是。之后请结合你自己的工程需要来选择。
    在这里插入图片描述
  • 然后我们可以看到如下界面,就是我们工程的界面了,点击左边的“+”,可以展开。
    在这里插入图片描述
  • 新建一个C语言文件:点击状态栏上的File->New
    在这里插入图片描述

可以看到新建的文件text1,然而这并不是我们想要的,我们点击1那里的save(保存),然后将文件名命名为main.c,这里的文件名可以起其他名字,但最好也具有辨识性。文件也可以保存在其他地方,但需要在KEIL里面配置好路径(这个可以先不了解)。但.c一定不能改!!因为我们使用C语言进行开发。如果你写的是汇编,当我没说~~,然后点击保存。
在这里插入图片描述

  • 添加文件到工程中:
    我们上面新建了一个.c文件,但目前这个文件并不在我们的工程目录里面,如下图:并没有看到一个main.c文件。
    在这里插入图片描述
    在你想要把文件添加到的分组上右键,我们这里就Source Group1一个分组,等以后可能会有不同的分组,分组的目的也是为了方便管理代码。注意不要点到Target1那里,然后选择添加已存在的文件
    在这里插入图片描述
    然后,会跳出工程所在的文件夹,找到要添加的文件,我们这里是main.c,然后添加。就可以在Source Group1下面看到main.c了。
    在这里插入图片描述

七、梦开始的地方-点亮一个LED

  • 单片机板子LED部分原理图。大家可以打开群里的“”“课程设计小系统板”PDF文件,这个就是我们这次使用的板子的与原理图,我们可以看到里面有一个黄色的方形,那就单片机的原理图表示,单片机上标了很多数字和引出来很多的线,那其实表示的是单片机的引脚,我们这次使用的单片机有32个引脚,不同封装的单片机引脚可能不同。我们编写单片机程序,本质是就是控制其引脚输出指定的电平(高或者低),来完成对应的功能。
    在这里插入图片描述
  • 从原理图可能看到单片机的每个引脚上都有对应的功能描述,比如:32号引脚上标了P0.3/AD3/TXD4。“/”分开的表示这引脚具有多种功能,我们可以通过对单片机进行不同的配置来选择不同的功能。我们这里仅对P0.3进行解释:P0代表了单片机的P0端口(一个端口一般对应8位,也就8个引脚),P0.3则表示是P0端口的3号引脚。AD3/TXD4属于单片机引脚的特殊功能,我们这里不需要关注。
  • 从原理图,我们需要知道某个LED连在单片机哪一个引脚上
    比如:图上标号为1(原理图上的元件都有一个对应的元件标号与其对应,因为原理图上LED的标号与元件重叠了,可能看的不是很清,所以我用红字标出了标号)的LED连在了P1(P1实际上是一个排针的接口,大家这里把它忽略掉就好了,只关注LED与单片机的连接关系)的4号上,而4连在了单片机的P0.0脚上。
  • 如何使点亮LED?
    LED(发光二极管):属于半导体器件,具有单向导电性。原理图中LED的符号是一个类似箭头的符号,“箭头”指向的方向代表了;LED导通的方向。只有在LED的正向有一个电压降,LED才会导通。 所以我们要做是如何使LED正向具有这个电压降。从图中我们可以知道LED的阳极全部连在了电源上(一般原理图用VCC代表电源),故阳极是高电平这点我们是无法改变的,我们能改变是单片机的引脚输出的电压。当使单片机引脚输出高电平(1)时,因为LED亮端都是高电平,没有电压降,故此时LED处于熄灭状态。只有当单片机引脚输出一个低电平(0),LED有一个正向的电压降,LED导通,有电流流过LED,LED此时会点亮。
  • 为什么LED与带VCC之间还串联了一个电阻呢?
    LED阳极与VCC之间那个方块表示的是一个电阻(原理图里一般用R标识),串电阻是因为LED导通的电流是有上限的,电流过大会烧毁LED,故串联一个电阻来限制流过LED的电流。如这里串了2000欧姆的电阻,板子上VCC是5V,这样,流过LED的电流最大为:5/2000=25mA。(LED电流范围大概是:10-30mA)。

接下来正式开始编程。

  • 打开刚才的main.c文件,然后再代码编辑框里面写编写代码。我这里给出一个点亮P0.3连接的LED(边上那个),大家可在此基础上试试点亮其他的LED,也可以尝试去点亮(熄灭)多个LED。
#include "reg51.h"//51单片机底层头文件
sbit LED0 = P0^3;//p要大写
void main()
{
    LED0 = 1;//灭掉led
    while(1)
    {
        LED0 = 0;//给p0.3一个低电平,点亮
    }
}
  • 对代码的说明:
    1#include "reg51.h"是一个51单片机的底层头文件,我们可以打开这个文件看看里面写了什么。我们将鼠标选在这一行,和右键会出现如下界面,我们可以通过图中的选项打开这个头文件。
    在这里插入图片描述
    可以从头文件里面看到,里面对P0等端口和单片机的一些特殊功能寄存器进行了定义。大家可以看main.c里面有用到P0.3,但并没有对P0^3进行任何定义,我们学习C语言应该知道,凡是需要用到的变量或者常量必须在使用前定义,我们在main.c里面没有定义,是因为P0 ^3在reg51.h这个头文件里面已经定义了,我们在程序中引用了这个头文件就不需要再对P0 ^3进行定义。就像大家写printf(“hello world!”);必须在程序里面引用#include "stdio.h"一样。因为printf函数是在stdio.h这个头文件定义的。
    2、 sbit 前面提到过,是声明一个位,P0^3表示的是P0端口的第3个端口,对应原理图里面的P0.3。我们这里定义一个位变量LED0,让其代表P0.3这个引脚。注意:所有的sbit定义必须在main函数外部。
    3、 在main函数里面我们先写了一句LED0 = 1,来灭掉P0.3对应的LED,然后写了一个死循环,这与我们平时在电脑写C语言不一样,我们想要单片机一直不停的按照一定顺序工作,不要去做我们不希望它去做的事(也就是程序不要跑飞了)。LED0 = 0;一句时P0.3引脚一直输出低电平,那么与此引脚连接的LED就会一直处于点亮的状态。

  • 我们写好程序之后需要生成.hex,然后通过STC-ISP把hex文件下载到单片机中去,生成hex文件需要对keil进行设置。如下图,点击红圈中的options for target。在这里插入图片描述
    然后点Output选项,把Create…勾上,然后ok,这样每次我们编译程序之后,keil都会重新生成一次hex文件。
    在这里插入图片描述

  • 对程序进行编译。其中:标号为“1”的表示对当前的文件进行翻译,“2”表示对修改过的文件进行编译,“3”表示全编译,对全部文件进行一次编译,这在当我们的程序文件比较多时编译的时间会比较长 。一般我们编译时点“2”也就是每次都对修改的文件再编译一下就可以了
    在这里插入图片描述
    如果编译时提示有错误,先解决第一个错误, 因为很多时候后面的错误是前面的错误引起的。

  • 程序编译没错误后,可以看到keil生成了hex文件。
    在这里插入图片描述

八、流水灯的几种打开方式

  • 什么是“流水灯”?
  • 如何在单片机中实现延时。
  • 麻雀虽小——
#include "reg51.h"
unsigned char LEDS[8]={};
void main()
{
	unsigned char i;
	i = 0;
	while(1)
	{
		for(i=0;i<8;i++)
		{
			if(i<4)
			P0 = LEDS[i];
			else 
			P2 = LEDS[i];
		}
		i = 0;
	}
}
#include "reg51.h"
void main()
{
	unsigned char i = 0;
	while(1)
	{
		for(i=0;i<8;i++)
		{
			P0 = ~(0X01<<i);
			Delayms(500);
		}
		i = 0;
	}
}

错误之处,请大家指正、批评!

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页