文章目录

  • 2 PIC工程建立与仿真
  • 3 单片机基础寄存器操作:
    • 3.1 IO
    • 3.2 模拟输入电压读取
    • 3.3 外部中断
    • 3.4 定时器中断
    • 3.5 串口UART
    • 3.6 IIC通信
  • 4 实际项目
  • 5 如何阅读代码
  • 6 如何把代码放到MPLAB V5.0+xc8 v2.0上工作?
    • 6.1 短暂的回顾
    • 6.2 xc8 v2.0程序结构
    • 6.3 移植操作指南
  • 7 常用的代码解释
    • 7.1 关于LCD1602
    • 7.2 memset清空 sprintf装填
  • 1 参考书籍:

基础操作需要看一下以下的博客,跟着走一遍。
安装MPLAB V4.05+XC8 V1.41,老师不会管你用什么版本,别的版本bug多,老版本反而好用:
https://blog.csdn.net/x1131230123/article/details/100907773
安装proteus 8.9:
https://blog.csdn.net/x1131230123/article/details/106951776
做一个基础实验(想改写到MPLAB V5+XC8 V2也看这里的博客6.3 移植操作指南):
https://blog.csdn.net/x1131230123/article/details/108757436

实物连接指南(持续更新):
https://blog.csdn.net/x1131230123/article/details/108780168

2 PIC工程建立与仿真

这一步主要教大家怎么做一个完整的工程,整个过程熟悉后,就可以做自己的实际项目了。
注意:下面你将阅读到的内容并不涉及到MPLAB和PROTEUS联合调试,先忘记你之前所学的然后跟着下面博客的去理解这个思路。
1、
首先去桌面创建2个文件夹,如下面这图。一个必须是英文的,一个可以中文;一个用于存放PIC工程的,一个存放proteus仿真文件。题外话:电脑用户名是中文的建议重装电脑系统。

2、
打开IDE

打开后:

3、
新建一个工程:
file->new project

嵌入式标准工程:

芯片型号

仿真器

npasm其实就是MPLAB自带的编译器,需要写汇编语言的。
下面的XC8是我们自己装的编译器产品,我们选XC8。注意!V1.41可以更好的编译,新的V2版本有的地方有bug,我不清楚指令的详细区别,所以直接建议就安装MPLAB V4.05 +XC8 V1.41 。

工程名字也必须英文,不然有bug:

选工程路径,去选择桌面上新建的那个文件夹,这样整个程序工程都会存在那个文件夹里。

编码选择UTF-8。什么是编码?
汉字编码有哪些? UTF-8才是最常用的编码,GB2312只是汉字编码太局限了。

完成后:

4、
为新建的工程添加一个main.c:右键点source files --> 左键点new --> 左键点main.c…

不要中文

这样就完成了!

5、
这个时候就可以编写单片机C程序了,写个简单的(下面这程序就是控制端口B的低四位输出0101电平):


#include <xc.h>// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG1
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator: Crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE =ON      // RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown Out Reset Selection bits (BOR disabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)void main(void)
{TRISB=0b11110000;//高四位输入 低四位输出PORTB=0b00000101;//高四位的设置无效 低四位输出0101while(1){}
}

在所有的预处理指令中,#pragma
指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。

不用管前面那些#pragma,那些全是对xc8编译器进行一些设置的,告诉编译器怎么处理怎么处理。

6、
写好程序后,怎么把程序弄到单片机里?单片机需要的是hex文件。
我们是C语言是人看的,我们需要需要借助MPLAB和XC8将C语言编译成hex文件。
点击下图里的图标就可以将C语言编译好。

注意:这里是编译,英文单词是build,编译的目的是将c语言转换成hex机器文件,单片机只需要这个文件就能够正确执行我们的程序。
你如果需要联调、调试、运行这几个关键词,英文单词是debug或者run等字眼,这类操作只在看程序运行到哪里,运行成了什么情况,是嵌入式程序员在开发过程中所需要的一种模式(要是经验足够也不需要这种模式)。这种事情要么需要proteus联调设置,要么需要实物单片机连接仿真器后插入了你的电脑,不要去点这些,除非你在自己进行联调操作或者调试实物操作。

会在底下看到编译提示:

make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory 'C:/Users/xd_du/Desktop/PICproject/helloworld.X'
make  -f nbproject/Makefile-default.mk dist/default/production/helloworld.X.production.hex
make[2]: Entering directory 'C:/Users/xd_du/Desktop/PICproject/helloworld.X'
"D:\Program Files (x86)\Microchip\xc8\v1.41\bin\xc8.exe" --pass1  --chip=16F887 -Q -G  --double=24 --float=24 --opt=+asm,+asmfile,-speed,+space,-debug,-local --addrqual=ignore --mode=free -P -N255 --warn=-3 --asmlist -DXPRJ_default=default  --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-osccal,-resetbits,-download,-stackcall,+clib   --output=-mcof,+elf:multilocs --stack=compiled:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -obuild/default/production/main.p1  main.c
"D:\Program Files (x86)\Microchip\xc8\v1.41\bin\xc8.exe"  --chip=16F887 -G -mdist/default/production/helloworld.X.production.map  --double=24 --float=24 --opt=+asm,+asmfile,-speed,+space,-debug,-local --addrqual=ignore --mode=free -P -N255 --warn=-3 --asmlist -DXPRJ_default=default  --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-osccal,-resetbits,-download,-stackcall,+clib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"      --memorysummary dist/default/production/memoryfile.xml -odist/default/production/helloworld.X.production.elf  build/default/production/main.p1
Microchip MPLAB XC8 C Compiler (Free Mode) V1.41
Build date: Jan 24 2017
Part Support Version: 1.41
Copyright (C) 2017 Microchip Technology Inc.
License type: Node Configuration:: warning: (1273) Omniscient Code Generation not available in Free modeMemory Summary:Program space        used     Dh (    13) of  2000h words   (  0.2%)Data space           used     2h (     2) of   170h bytes   (  0.5%)EEPROM space         used     0h (     0) of   100h bytes   (  0.0%)Data stack space     used     0h (     0) of    60h bytes   (  0.0%)Configuration bits   used     2h (     2) of     2h words   (100.0%)ID Location space    used     0h (     0) of     4h bytes   (  0.0%)You have compiled in FREE mode.
Using Omniscient Code Generation that is available in PRO mode,
you could have produced up to 60% smaller and 400% faster code.
See http://www.microchip.com/MPLABXCcompilers for more information.make[2]: Leaving directory 'C:/Users/xd_du/Desktop/PICproject/helloworld.X'
make[1]: Leaving directory 'C:/Users/xd_du/Desktop/PICproject/helloworld.X'BUILD SUCCESSFUL (total time: 1s)
Loading code from C:/Users/xd_du/Desktop/PICproject/helloworld.X/dist/default/production/helloworld.X.production.hex...
Loading completed

我们的hex文件在哪里?编译完成后,我们就可以在桌面那个工程文件夹里去找下图里这个hex文件,这个文件就是机器文件。proteus加载这个文件就可以执行我们写的程序。!!!!找到这个文件我们就已经成功了!

题外话:编译的时候提示了一句话:

You have compiled in FREE mode.

题外话:所以如何才能不处于免费模式?右键工程–>properties–>按图里的点击。
题外话:作用:此选项选择编译器的基本操作模式。可用类型有pro、std和free。在PRO模式下运行的编译器使用完全优化并生成最小的代码大小。标准模式使用有限的优化,而自由模式只使用最小的优化级别,将生成相对较大的代码。
提示:选择PRO在很多时候都不是一个明智的选择,PRO模式在编译器会“智能地”改变一些C语言的汇编实现方法,这有时候会有益于代码的最优化,但有时候会显得有些“智障”,会让能你认为能好好工作的C代码工作起来不正常。这个PRO主要是提供给有经验的嵌入式开发工程师用于优化代码的。

7、
MPLAB中的事情已经进行完了,现在你已经知道怎么使用MPLAB建立工程,如何编写程序和编译程序,编译后的hex文件目录在哪里。
其实写好程序后,就可以链接仿真器进行下载(烧写)程序了。链接仿真器后,下面的run图标或者debug图标点一下,MPLAB都会自动讲hex文件烧写到实物单片机中,单片机就能够运行起来。这一步的操作是在调试实物的时候所用到的,字眼是debug。这里只是顺便提及一下,跟我们想要进行的仿真没有丝毫联系。

现在可以谈谈另一件事情,如何proteus仿真?
Proteus软件里面含有很多单片机和外部器件,能够模拟实物电路的运行。如果我们在Proteus软件里连接好需要的实物器件,然后将写好的程序(hex文件)加载到Proteus软件里的单片机器件里,那在Proteus软件中我们就可以看到整个电路的工作情况。我们的关注点就放到了Proteus软件中的器件连接中了。

8、
Proteus软件的安装和基础使用参见这个链接:
https://blog.csdn.net/x1131230123/article/details/106951776
新建仿真图–>添加器件PIC16F887

将hex文件加载到Proteus软件里的单片机器件里:双击单片机器件进入下图这个设置界面—>点击打开文件符号—>选择桌面上工程里的hex文件—>打开—>点击OK—>成功。这里没有详细截图,看下图里的左边箭头去找hex文件即可!

此时可以看到Proteus软件左下角,分别是开始仿真和停止仿真按钮。我们点击开始仿真。

仿真运行后,可以看到单片机的端口B四位电平,蓝色就是低电平的意思,红色就是高电平的意思,这里就是0101的电平。如果这引脚连接了LED灯,LED灯就可以点亮。由此可见,程序生效了,单片机正常工作中。

3 单片机基础寄存器操作:

3.1 IO

设置一个端口为输出 TRISA0=0
设置一个端口为输入 TRISA0=1
设置一个端口输出高电平 RA0=1
设置一个端口输出低电平 RA0=0
同时设置8个端口响应使用TRISA PORTA
设置B C D端口类似。

3.2 模拟输入电压读取

设置某个引脚为输入–>打开模拟输入

3.3 外部中断

详细看书。

3.4 定时器中断

详细看书。

3.5 串口UART

详细看书。

3.6 IIC通信

详细看书。

4 实际项目

PIC16F887 单片机 PROTEUS 仿真 C程序 测温系统 TC74 DS18B20
PIC16F887 单片机 PROTEUS 仿真 C程序 信号发生器
PIC16F887 单片机 PROTEUS 仿真 C程序 温控电机
PIC16F887 单片机 PROTEUS 仿真 C程序 数字时钟 万年历 DS1302 阴历显示
PIC16F887 单片机 PROTEUS 仿真 C程序 抢答器
PIC16F887 单片机 PROTEUS 仿真 C程序 可存储电子琴 PIC
PIC16F887 单片机 PROTEUS 仿真 C程序 模拟电话拨号计算器 密码锁
PIC16F887 单片机 PROTEUS 仿真 C程序 电子密码锁
PIC16F887 单片机 PROTEUS 仿真 C程序 智慧门铃呼叫系统 门铃一拖 3
PIC16F887 单片机 PROTEUS 仿真 C程序 病床呼叫系统
PIC16F887 单片机 PROTEUS 仿真 C程序 测温系统 DS18B20 TC74
PIC16F887 单片机 PROTEUS 仿真 C程序 数字点餐系统

5 如何阅读代码

整个程序结构一般如下:

#include <xc.h>
//part 0//
可能会放置一些子函数的声明
C语言嘛,子函数无非就是先声明,后定义。//part 1//
各种杂七杂八的子函数放在这个地方
显示屏子函数
温度传感器子函数
报警判断子函数
按键检测子函数void main( void )
{//part 2//调用一些初始化程序比如单片机引脚要读取按键高低电平,就得把这个引脚设置为输入方向比如定时器中断初始化,设置每隔2ms执行一次中断函数while(1){//part 3//这里是一个死循环体这个位置要写单片机不断重复在做的事情,永不停息比如检测按键输入,有输入了根据输入处理一下比如不断调用温度读取函数,然后把结果显示出来}}//part 3//
这里这个带了interrupt 这个函数就是中断函数
这个函数独立于所有函数之外,单独看这个函数
这个函数是需要被触发的
都是要靠设置单片机寄存器来做到的
比如在main里初始化的时候设置了定时器1的2ms中断,那么每过2ms就会执行一次high_isr()函数,在函数里面判断寄存器TMR1IF 就可以知道是定时器的2ms事件。
void interrupt high_isr( void )
{if ( TMR1IF ){TMR1IF   = 0;//清除标志位//part 4//这里需要写定时执行的东西,比如我设置了一个变量是秒针倒计时,每一秒就减少1那么我得这么写:变量1 ++;if(变量1加到了500){变量1 = 0;秒针 --;  (变量1每2ms执行一次减少1,500次花费时间1s)}}
}

看懂上面的框架后,我们就可以的代码,我们可以依照以下几个注意点去看程序:
(1)在MPLAB中建立好工程,利用好MPLAB去阅读程序;
(2)MPLAB有个窍门,在工程已经被编译后,我们可以 按住ctrl 然后鼠标左键点函数名字或变量名字去跳转,直接跳转到函数定义的地方。更需要提出的是,在子函数定义处再次ctrl+左键点函数名字,会跳转到子函数声明处。
(3)ctrl+F进入查找,可以通过Next去查看main.c整个文件中的这个查找字符串出现的每一个地方。方便看函数都在哪里用了。

(4)注重函数或者变量名称+注重分类。比如LCD1602驱动函数就是挨着的一堆,函数名都差不多有个LCD字样。有意识地去多输入一个回车,使得与其他代码间隔远一下,自己更好分清。

(5)建议别从main.c文件的第一行开始看,懂了整个程序结构这个鸭子类型后,单片机上电后就执行main()函数里的,我们就可以直接从main()开始看,先初始化啥啥啥的,然后死循环啥的。别的子函数都是调用,既然在递归,那我们更需要关注最上层,从最上面的调用通过注意点(2)的窍门去看。这样更能注意到 题目功能的实现走向,而不是注意到底层都怎么写的,为什么那么写。

注意:我这里再梳理一下,如何看懂别人的程序是有一个过程的。首先你在脑海里面要有一个程序的大体结构,然后你应该从main()函数开始看,利用鼠标哪里不会点哪里,看看注释帮助自己理解这个函数是在干啥, C语言库函数不理解的直接就baidu学习。其实了解程序结构以后就大概了解整个实现功能的过程,我们无非就是去关注上电之后的初始化过程、主函数在循环处理的过程、中断函数在中断处理哪些事件的过程。最终最终代码就是要实现功能,我们能把代码和功能相关联起来那就成功了!

6 如何把代码放到MPLAB V5.0+xc8 v2.0上工作?

6.1 短暂的回顾

这个话题其实我不太想说,因为以前很多代码资料都是建立在PICC或者xc8 v1.41上(包括大家的教科书上),代码资料多了,做设计就相对来说比较容易,因为这就意味着你可以去找别人的代码资料复制到自己的工程里面去用,并且不用担心因为编译器不同带来的影响(编译器差距太大,会导致最后编译出来的代码不一样,可能我之前在淘宝找的资料能够用xc8 v1.41编译器在实物上运行,修改编译器可能会导致很大的改变,这是我不愿意看到的,不愿意花时间去调试这些bug)。
但总有人问,我来梳理一下怎么去移植。
首先让我们去关注一下xc8 v1.41上面的程序:

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>/* CONFIG1 */
#pragma config FOSC = XT        /* Oscillator Selection bits (XT oscillator: Crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN) */
#pragma config WDTE = OFF       /* Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register) */
#pragma config PWRTE = OFF      /* Power-up Timer Enable bit (PWRT disabled) */
#pragma config MCLRE =ON        /* RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD) */
#pragma config CP = OFF         /* Code Protection bit (Program memory code protection is disabled) */
#pragma config CPD = OFF        /* Data Code Protection bit (Data memory code protection is disabled) */
#pragma config BOREN = OFF      /* Brown Out Reset Selection bits (BOR disabled) */
#pragma config IESO = OFF       /* Internal External Switchover bit (Internal/External Switchover mode is disabled) */
#pragma config FCMEN = OFF      /* Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled) */
#pragma config LVP = OFF        /* Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming) *//* CONFIG2 */
#pragma config BOR4V = BOR40V   /* Brown-out Reset Selection bit (Brown-out Reset set to 4.0V) */
#pragma config WRT = OFF        /* Flash Program Memory Self Write Enable bits (Write protection off) */void main( void )
{while(1){}}
void interrupt high_isr( void )
{}

上面的程序就是一般的xc8 v1.41上面的程序,一起来看一下都有哪些部分。
第1个部分是头文件,其实这个部分更应该放在接下来所要说的第2个部分之后。

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

第2个部分就是编译器预设置,这个部分xc8 v1.41和xc8 v2.0一样规则。#pragma这种指令就是去设置编译器的,告诉编译器应该怎样编译这个c程序。

/* CONFIG1 */
#pragma config FOSC = XT        /* Oscillator Selection bits (XT oscillator: Crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN) */
#pragma config WDTE = OFF       /* Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register) */
#pragma config PWRTE = OFF      /* Power-up Timer Enable bit (PWRT disabled) */
#pragma config MCLRE =ON        /* RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD) */
#pragma config CP = OFF         /* Code Protection bit (Program memory code protection is disabled) */
#pragma config CPD = OFF        /* Data Code Protection bit (Data memory code protection is disabled) */
#pragma config BOREN = OFF      /* Brown Out Reset Selection bits (BOR disabled) */
#pragma config IESO = OFF       /* Internal External Switchover bit (Internal/External Switchover mode is disabled) */
#pragma config FCMEN = OFF      /* Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled) */
#pragma config LVP = OFF        /* Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming) *//* CONFIG2 */
#pragma config BOR4V = BOR40V   /* Brown-out Reset Selection bit (Brown-out Reset set to 4.0V) */
#pragma config WRT = OFF        /* Flash Program Memory Self Write Enable bits (Write protection off) */

第3个部分就是主函数,这个部分xc8 v1.41和xc8 v2.0一样规则。

void main( void )
{while(1){}}

第4个部分中断,这个部分xc8 v1.41和xc8 v2.0命名规则不一样。

void interrupt high_isr( void )
{}

6.2 xc8 v2.0程序结构

下面给出一个xc8 v2.0上面的程序,记住程序结构:


/* CONFIG1 */
#pragma config FOSC = XT        /* Oscillator Selection bits (XT oscillator: Crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN) */
#pragma config WDTE = OFF       /* Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register) */
#pragma config PWRTE = OFF      /* Power-up Timer Enable bit (PWRT disabled) */
#pragma config MCLRE =ON        /* RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD) */
#pragma config CP = OFF         /* Code Protection bit (Program memory code protection is disabled) */
#pragma config CPD = OFF        /* Data Code Protection bit (Data memory code protection is disabled) */
#pragma config BOREN = OFF      /* Brown Out Reset Selection bits (BOR disabled) */
#pragma config IESO = OFF       /* Internal External Switchover bit (Internal/External Switchover mode is disabled) */
#pragma config FCMEN = OFF      /* Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled) */
#pragma config LVP = OFF        /* Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming) *//* CONFIG2 */
#pragma config BOR4V = BOR40V   /* Brown-out Reset Selection bit (Brown-out Reset set to 4.0V) */
#pragma config WRT = OFF        /* Flash Program Memory Self Write Enable bits (Write protection off) */#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void main( void )
{while(1){}}
void __interrupt() ISR( void )
{}

6.3 移植操作指南

1、假如你的程序中含有中断函数,你应该把xc8 v1.41的中断名字改为xc8 v2.0的中断名字。(题外话:做了这一步你的程序基本就OK了,但我也没有调试过实物,不知程序到实物是否正常,建议能不搞xc8 v2.0就别搞,一时的安逸可能带来更多的挫折。)
!!!!据说应该在main()函数之前添加中断的函数声明:void __interrupt() ISR( void ); 不然会乱码。(侧面反应出我们并不熟悉xc8 v2.0,这里行了也不能保证实物正常吧。)
xc8 v1.41的中断名字

void interrupt high_isr( void )

xc8 v2.0的中断名字

void __interrupt() ISR( void )

2、如果你的程序中含有DS1302驱动程序,并且程序中还有下面两句话:

unsigned char        time_rx @ 0x30;                         /* 定义接收寄存器 */
static volatile bit time_rx7 @ (unsigned) &time_rx * 8 + 7; /* 接收寄存器的最高位 */

这种写法在xc8 v2.0中不再支持,这两句话其实是去取最高位地址bit数据,写法比较高级。你需要把这两句话删除掉。并且你需要把下面的函数修改为下面这个样子(可以直接复制下面这个函数去替换程序中原来的函数,找好位置 别搞错了)。

/****************************************************************************
* 名    称:time_read_1()
* 功    能:读一个字节
* 入口参数:
* 出口参数:
* 说    明:
****************************************************************************/
unsigned char time_read_1()
{int j;                                  /* 设置循环变量 */unsigned char  time_rx;TRISC4 = 1;                             /* 设置数据口方向为输入 */for ( j = 0; j < 8; j++ )               /* 连续读取8bit */{sclk      = 0;            /* 拉低时钟信号 */time_rx        = time_rx >> 1; /* 接收寄存器右移1位 */if(i_o){time_rx |= 0x80;}sclk        = 1;            /* 拉高时钟信号 */}TRISC4    = 0;                            /* 恢复数据口方向为输出 */sclk   = 0;                            /* 拉低时钟信号 */return(time_rx);                        /* 返回读取到的数据 */
}

3、你或许更应该将编译器预设置部分的代码放到程序的最开始,但我个人认为其实没什么影响。

4、如果你在移植操作中遇到更多的报错信息,可以告诉我。我的处理方式也很简单,我会根据软件下面的报错信息找到对应的报错点,然后根据经验修改报错点程序即可。

7 常用的代码解释

看到这里,你应该有一个基本观念,不要拿“我们没学过”当借口,遇到程序看不懂就知道退缩,怎么学也学不会。
多找资料,多复习C语言,遇到问题敢于写个小程序做做实验。你自己想要写出自己的程序的第一步,就是模仿学习别人的程序。

7.1 关于LCD1602

LCD1602使用LCD_WRITE()函数执行写入命令操作或者写入数据操作。
写入命令0x80+x,代表想要显示的起始位置是LCD1602的第0行,第x列。(一共有2行,16列,x可以等于0到15,y可以等于0到1)。
写入命令0xC0+x,代表想要显示的起始位置是LCD1602的第1行,第x列。
char *s是一个指针,指向一个字符串首地址的话,while (*s)会一直判断当前是不是为空,不为空就向1602写入指针指向的字符 LCD_WRITE(*s, DATA);,写入后指针后移一个字符 s++。
举例 lcd1602_write_str(3,1,“hello”); 就是想在第3列,第1行开始显示,显示一个字符串hello。指针最初指向’h’,写入后后移,直到指针指向空。

/* 写字符串 */
void lcd1602_write_str(unsigned char x, unsigned char y, char *s)
{if (y == 0){LCD_WRITE(0x80 + x, COM);//写入命令}else{LCD_WRITE(0xC0 + x, COM);//写入命令}while (*s){LCD_WRITE(*s, DATA);//写入数据s++;}
}

7.2 memset清空 sprintf装填

学了void lcd1602_write_str(unsigned char x, unsigned char y, char *s)函数后,写显示函数就简单了。
你会定义一个数组,比如是 buffer[16]。
当你想显示hello的时候,你可以这么写:

buffer[0]='h';
buffer[1]='e';
buffer[2]='l';
buffer[3]='l';
buffer[4]='o';
buffer[5]=0; //必须给0,指针指到这里认出0就代表空了
lcd1602_write_str(3,1,buffer);//指针指向数组的首位,然后指针一直后移,最终写入完整hello

但上面的方法不方便,比如你想显示一个变量abc,你得这么写:

int abc=54;
buffer[0]='0'+abc%100/10;//百分号是取余运算,/是整除运算,可百度。加'0'是为了变成ascii码。
buffer[1]='0'+abc%10;
buffer[2]=0;
lcd1602_write_str(3,1,buffer);

C语言发明者就发明了一个通用函数sprintf,这让这个操作简单了。
比如你想把字符串“hello”装入数组里,你可以直接:

sprintf(buffer, "hello");//装填

C语言就会把字符串一个一个填入数组,这个时候你就可以调用类似于lcd1602_write_str(3,1,buffer);这样去显示了。
比如你想把abc变量变成字符串然后写入数组,你可以直接:

sprintf(buffer, "hello %d",abc);//装填  %d是十进制表示的意思
sprintf(buffer, "hello %d  %d",abc, abc);//可以一次装填多个变量

第一个参数是数组指针 buffer
第二个参数是字符串样式
第三个参数和后面参数是一些变量
这个时候还有个问题,就用sprintf(buffer, "hello");//装填举例,执行这句话后数组里是变成字符串了,此时有:

buffer[0]='h';
buffer[1]='e';
buffer[2]='l';
buffer[3]='l';
buffer[4]='o';

但是并不能保证数组里面其他的元素是0!!
C语言发明者就搞了一个memset函数,能够初始化一切数组。
此时就可以:

memset(buffer, 0, sizeof(buffer));

第一个参数是数组指针 buffer
第二个参数是想把数组里面所有元素初始化为0
第三个参数是想初始化多长的元素,sizeof(buffer)表示想初始化数组里所有元素。

1 参考书籍:



PIC16F887 实战编程 单片机编程 基础实验教程相关推荐

  1. 计算机硬件系统实验教程控制器代码,计算机硬件基础实验教程

    <计算机硬件基础实验教程>是2005年清华大学出版社出版的图书,作者是白中英 .杨春武. 中文名 计算机硬件基础实验教程 出版社 清华大学出版社 页    数 269 页 开    本 1 ...

  2. 大学计算机基础实验教程实验2-7,大学计算机基础实验教程(Windows 7+Office 2010)(第2版)...

    大学计算机基础实验教程(Windows 7+Office 2010)(第2版) 语音 编辑 锁定 讨论 上传视频 <大学计算机基础实验教程(Windows 7+Office 2010)(第2版) ...

  3. 计算机应用基础实验教程练习题答案,计算机应用基础实验教程答案.doc

    计算机应用基础实验教程答案 [篇一:大学计算机基础习题与实验指导 --课后习题答 案] ss=txt> 习题答案 第二章 1,简述计算机中如何区分汉字编码和 ascii 码 asc Ⅱ码与汉字编 ...

  4. 计算机硬件实验教程pdf,计算机硬件技术基础实验教程答案(重庆大学)

    计算机硬件技术基础实验教程答案(重庆大学) 计算机硬件技术基础实验教程答案 实验一:简单程序设计实验 (1)编写一个 32 位无符号数除法的程序,要求将存放在 NUM1 中的 32 位无符号数与存放 ...

  5. 大学计算机基础:信息处理技术实验教程,大学计算机基础实验教程

    大学计算机基础实验教程 (2011年清华大学出版社出版的图书) 语音 编辑 锁定 讨论 上传视频 <大学计算机基础实验教程>是2011年清华大学出版社出版的图书,作者是周晓梅. 书     ...

  6. 大学计算机实验教程实验6,《大学计算机基础实验教程》参考答案.(6页)-原创力文档...

    <大学计算机基础实验教程>参考答案 第1章参考答案 一.单项选择题 1.B 2.B 3.C 4.D 5.D 6.B 7.A 8.B 9.D 10.B 11.A 12.C 13.B 14.A ...

  7. 计算机基础实验教程第二版苏州大学出版社,计算机基础实验教程

    计算机基础实验教程 (2008年机械工业出版社出版的图书) 语音 编辑 锁定 讨论 上传视频 <计算机基础实验教程>是2008年机械工业出版社出版的图书,作者是李晓宾.本书主要包括了计算机 ...

  8. 计算机文化基础实验教程石油答案,中石油第九版计算机文化基础实验教程习题答案.doc...

    中石油第九版计算机文化基础实验教程习题答案.doc 第一章 一.单项选择题 1.A 2.A 3.A4.A5.C6.D7.C8.B9.C 10.B11.B12.D13.A14.C15.C16.C17.A ...

  9. 计算机应用基础实验教程电子,计算机应用基础实验教程-Windows 7+Office 2010.pdf

    " " 普通高等教育 十二五 规划教材 计算机应用基础实验教程 ---Windows7 +Office2010 主 审 李仲麟 主 编 郑馥丹 参 编 付春英 张伟娜 王素丽 李慧 ...

  10. 计算机文化教程实验基础知识,计算机文化基础实验教程

    摘要: <计算机文化基础实验教程(第2版)>是与<计算机文化基础>配套使用的上机实习指导与测试用书,编写<计算机文化基础实验教程(第2版)>的主要目的是便于教师的教 ...

最新文章

  1. Hbase基础(特点、架构、应用场景、集群搭建、HA设计)这一篇就够了
  2. Centos用yum安装X Winodw
  3. WebSphere MQ----通道
  4. 机器学习的一些很好的博客
  5. GIMP 2.10教程
  6. 02 - 替换SetInput方法 VTK 6.0 迁移 (2013-06-30 16:22)
  7. ddns 被解析为127.0.0.1_我为北京冬奥加油,2020.2.1-2.10冬奥知识分享
  8. 用javascript实现以下功能!_JavaScript实现汉字转拼音功能
  9. BroadcastReceiver广播
  10. UIView方法,属性的集合
  11. java火币网做接口_火币网API文档——Websocket 请求与订阅示例
  12. 机器学习 - [源码实现决策树小专题]决策树如何分裂以拓展节点(以及在不允许调用sklearn等库的源代码实现)
  13. bzoj4567: [Scoi2016]背单词
  14. matlab读取npy文件
  15. Centos宝塔面板清理垃圾空间
  16. CESIUM例子学习(一)——动态模型加载
  17. vue-quill-editor编辑器踩坑
  18. godot引擎学习6
  19. OKCC外呼中心为什么要把语音引入WEB中?
  20. YUV RGB格式分析,以及对应码率(带宽)计算

热门文章

  1. txt转excel 处理数据
  2. openstack学习之路-python运维(network)
  3. 查看python的模块和函数帮助文档方法
  4. Java使用OpenOffice实现Office系列文件转Pdf
  5. JSP编程中遇到的问题及解决
  6. 计算机组成原理白中英知识点总结,计算机组成原理重点整理(白中英版)
  7. c语言函数.pdf文档,c语言库函数表.pdf
  8. 李峋同款的C语言动态爱心代码(终于不是html的啦)
  9. 【数字信号去噪】基于matlab遗传算法优化变分模态分解VMD数字信号去噪(目标函数为样本熵)【含Matlab源码 1982期】
  10. linux中安装apk软件,Linux下安装软件的几种方式