2017/3/22 如何用C 来完成SN8系列芯片的程序设计 2017/3/22.

Slides:



Advertisements
Similar presentations
现代电子技术实验 ——综合实验之单片机部分
Advertisements

C语言程序设计 主讲教师 :张群燕 电话:
第4章 條件判斷與迴圈 Java 2 程式設計入門與應用.
第一章 C语言概述 计算机公共教学部.
编译原理上机实习
本章内容: 中断的概念 MCS-51单片机中断系统 外部事件中断及应用
8051 指令.
第四章 指令系统及汇编语言程序设计.
本章分为四节,主要介绍: 4.1 程序编制的方法和技巧 4.2 源程序的编辑和汇编 4.3 基本程序结构 4.4 常用程序举例.
项目2 2个LED发光二极管控制 知识与能力目标 熟悉单片机的I/O口功能与特性。
得技通电子 问题 1 右何者非為假指令 (1) XRL (2) EQU (3) MACRO (4) ORG.
本章小结 C51单片机指令系统概述 C51单片机寻址方式 C51单片机指令系统
单片机原理与应用.
C语言程序设计 第十二章 位运算.
第一章 C语言概述.
主讲教师:吴琼 微信群:C语言2016 QQ群: 密码scu2016 昵称:“真名+学号”
Class 2 流程控制-選擇敘述與迴圈.
第二章 C# 基础知识.
第9章 数模转换器与模数转换器 本章学习目标 了解数模转换器的工作原理及性能指标 掌握模数转换器的应用 掌握数模转换器的应用.
第2章 MCS-51单片机指令系统与汇编语言程序设计
第二部分 微机原理 第4章 汇编语言 程序设计 主讲教师:喻红.
本章内容: 中断的概念 MCS-51单片机中断系统 外部事件中断及应用
一、任务描述 二、任务分析 三、任务演示 四、相关知识 五、任务布置. 一、任务描述 二、任务分析 三、任务演示 四、相关知识 五、任务布置.
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
编译原理与技术 类型检查 2018/11/21 《编译原理与技术》-类型检查.
第3章 C 語言的基本知識.
第十一章 复位、时钟和省电方式控制.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
第一章 8086程序设计 第二章 MCS-51程序设计 第三章 微机基本系统的设计 第四章 存贮器与接口 第五章 并行接口
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
第七章 定时/计数器.
周国运 Keil C51应用 主 页:
C++语言程序设计 第二章 C++简单程序设计.
第五章 C/C++及汇编语言的混合编程 5.1 ARM C/C++编译器 5.2 在C/C++程序中内嵌汇编指令
6.1 输入/输出 6.2 CPU与外设数据传送方式 6. 3 MCS-51中断系统 6. 4 中断应用举例
第三章 数据类型、运算符与表达式.
第三章 C# 基础知识.
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年11月19日.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
合泰半导体股份有限公司 技术讲座 - Holtek V3 C Compiler介绍 主讲人:王幼端 2017/06/15.
第4章 汇编语言程序格式  汇编程序功能  伪操作  汇编语言程序格式  汇编语言程序的上机过程.
Holtek C Compiler V3--advanced
C语言概述 第一章.
第1讲 C语言基础 要求: (1) C程序的组成 (2) C语言的标识符是如何定义的。 (3) C语言有哪些基本数据类型?各种基本数
本章内容 MCS-51单片机指令系统的格式 MCS-51单片机寻址方式 指令系统的分析
第 二 章 数据类型、运算符与表达式.
单片机原理与应用 主讲人:张荣刚 福建师范大学福清分校.
第二章 Java基本语法 讲师:复凡.
C语言程序设计 李祥 QQ:
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第二章 Java语法基础.
第3章 数据类型、运算符与表达式.
第二章 类型、对象、运算符和表达式.
汽车单片机应用技术 学习情景1: 汽车空调系统的单片机控制 主讲:向楠.
单片机原理及应用 实践部分 主讲人:刘 强 四川工商学院单片机教学团队 单片机原理及应用 实践部分 主讲人:刘 强
第二章 基本数据类型 ——数据的表示.
Review 1~3.
四、手工汇编 完成汇编的方法有两种:手工汇编和汇编程序汇编 1.手工汇编步骤 A
#include <iostream.h>
第十二章 位运算.
单片机应用技术 (C语言版) 第4章 C51程序设计入门
单片机应用技术 (C语言版) 第3章 MCS-51指令系统及 汇编程序设计
微机原理与接口技术 第5章 汇编语言程序设计 西安邮电大学计算机学院 王 钰.
大数据搜索挖掘实验室 第五章 子程序设计 张华平 副教授 博士 Website: 大数据搜索挖掘实验室
基本資料型態 變數與常數 運算子 基本的資料處理 授課:ANT 日期:2014/03/03.
第4章 MCS-51汇编语言程序设计 教学基本要求: (1)、了解MCS-51汇编语言程序设计的特点;
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
Presentation transcript:

2017/3/22 如何用C 来完成SN8系列芯片的程序设计 2017/3/22

Review 内嵌汇编 程序结构 SN8 C studio 的安装与使用 数据类型与运算 程序流程控制 函数 2017/3/22 Review SN8 C studio 的安装与使用 数据类型与运算 程序流程控制 函数 结构体、联合在SN8 C程序中的应用 中断 位操作 内嵌汇编 程序结构

2017/3/22 SN8 C studio 的安装与使用 SN8 C studio 的安装 SN8 C studio应用实例

数据类型与运算 数据类型 基本类型 字符型(char) 整型(int) 长整型(long) 浮点型(float) 构造类型 2017/3/22 数据类型与运算 数据类型 基本类型 字符型(char) 整型(int) 长整型(long) 浮点型(float) 构造类型 数组(array) 结构体(struct) 共用体(union) 枚举(enum) 指针类型 空类型

专有数据类型 数据类型 Size(Byte) 数据取值范围 Signed char(short、int) 1 -128~+127 2017/3/22 专有数据类型 数据类型 Size(Byte) 数据取值范围 Signed char(short、int) 1 -128~+127 Unsigned char(short、int) 0~255 Signed long 2 -32768~+32767 Unsigned long 0~65535 float、double 4 Pointer enum

常量的定义 先来看看汇编的常量定义: door_service_c equ #80 ;80ms去门抖动 2017/3/22 常量的定义 先来看看汇编的常量定义: door_service_c equ #80 ;80ms去门抖动 t0int_c equ #224 ;t0中断时间 segment_c equ #3 ;最多3段烹调 注:上面数值前的#号,是SN8ASM的符号,用于提示后面的是立即数。

再来看看用SN8 C是如何定义相同的常量的: 2017/3/22 常量的定义 再来看看用SN8 C是如何定义相同的常量的: #define door_service_c 80 //80ms去门抖动 #define t0int_c 224 //t0中断时间 #define segment_c 3 //最多3段烹调 NOTE: 对习惯于写汇编的人来说,千万注意C对大小写敏感!并从变量定义就要开始注意!

数值列表 汇编的表: disp_automenu: ;显示菜单用第二数字表格 dw 0000h dw 0ae1fh ;A-1 2017/3/22 数值列表 汇编的表: disp_automenu: ;显示菜单用第二数字表格 dw 0000h dw 0ae1fh ;A-1 dw 0ae2fh ; dw 0ae3fh ; dw 0ae4fh ; dw 0ae5fh ; dw 0ae6fh ; dw 0ae7fh ; 表的内容都是用DW关键字来定义

变量定义与限制 __RAM与__ROM关键字的使用: 将变量存放在RAM中 [默认] 2017/3/22 变量定义与限制 __RAM与__ROM关键字的使用: Unsigned int __RAM ramVeriable; __RAM unsigned int ramVeriable2; Unsigned int __ROM romVeriable; __ROM unsigned int romVeriable2; 将变量存放在RAM中 [默认] 将变量存放在ROM中

常量数值列表定义 C定义的数值列表: unsigned long __ROM disp_automenu[]= { 2017/3/22 常量数值列表定义 C定义的数值列表: unsigned long __ROM disp_automenu[]= { 0x0000,0x0ae1f,0x0ae2f,0x0ae3f, 0x0ae4f,0x0ae5f,0x0ae6f,0x0ae7f }; 定义一个数组来存储这些表的数值

变量的定义 汇编的定义变量的方法: .DATA org 0h temp1 ds 1 分别占用的Byte单位的RAM空间 temp2 ds 1 2017/3/22 变量的定义 汇编的定义变量的方法: .DATA org 0h temp1 ds 1 temp2 ds 1 led_dp ds 1 step ds 1 Job_mode ds 2 Pow_mode ds 4 分别占用的Byte单位的RAM空间 用DS关键字来定义变量空间

C支持不同长度的变量类型,这样就方便了程序员的使用 2017/3/22 变量的定义 用C定义变量: unsigned int temp1; unsigned int temp2; unsigned int led_dp; unsigned int step; unsigned long job_mode; unsigned long power_mode1; float powerValue; int temp1_1; long temp2_2; C支持不同长度的变量类型,这样就方便了程序员的使用

(un)signed int/short/char 2017/3/22 变量定义的对比 ASM.的定义 C的定义 DS 1 (un)signed int/short/char DS 2 (un)signed long DS 4 Float/double

能使用无符号数的都使用无符号数,以免处理出错,因为芯片内部是以无符号数处理的。 2017/3/22 变量类型的选择 在选择数据类型的时候,在能够顺利完成功能的情况下,请尽量选择占空间少的数据类型,这样不管是在RAM空间使用上还是在产生代码效率上都有很多的好处! 能使用无符号数的都使用无符号数,以免处理出错,因为芯片内部是以无符号数处理的。

数据的存储 SN8芯片的数据存储区 Bank0 0000H 通用存储区 128Byte 用户存储区 007FH 0080H 系统寄存器区 2017/3/22 数据的存储 SN8芯片的数据存储区 Bank0 0000H 通用存储区 128Byte 用户存储区 007FH 0080H 系统寄存器区 80H~FFH为系统寄存器区域 00FFH Bank1 00100 更多的用户存储区 01FFh

系统寄存器 系统寄存器表 2017/3/22 1 2 3 4 5 6 7 8 9 A B C D E F L H R Z Y X PFLAG 1 2 3 4 5 6 7 8 9 A B C D E F L H R Z Y X PFLAG RBANK - AMPM P4CON DAM ADM ADB ADR PEDGE P2M P4M P5M INTRQ INTEN OSCM WDTR TC0R PCL PCH P0 P2 P4 P5 T0M TC0M TC0C TC1M TC1C TC1R STKP P0UR P2UR P4UR P5UR @YZ STK7L STK7H STK6L STK6H STK5L STK5H STK4L STK4H STK3L STK3H STK2L STK2H STK1L STK1H STK0L STK0H

这些系统寄存器都是以大写字母进行定义的,在程序中使用时要注意这一点。 2017/3/22 .H档中对系统寄存器定义 #include <sn8p2708a.h> 每个程序都要包含相应芯片的.H档 #define L (*((__RAM unsigned int*)0x80)) #define H (*((__RAM unsigned int*)0x81)) #define R (*((__RAM unsigned int*)0x82)) #define Z (*((__RAM unsigned int*)0x83)) #define Y (*((__RAM unsigned int*)0x84)) #define X (*((__RAM unsigned int*)0x85)) #define PFLAG (*((__RAM unsigned int*)0x86)) …… 这些系统寄存器都是以大写字母进行定义的,在程序中使用时要注意这一点。

2017/3/22 程序流程控制 顺序结构 判断分支结构 串行分支结构 并行分支结构 循环结构

2017/3/22 顺序结构 顺序结构流程 A操作 B操作 框内A、B操作按顺序执行

顺序结构的实现对比 .ASM .C b0bset key_bibi_f mov a,#0f0h mov menu_disp_h,a 2017/3/22 顺序结构的实现对比 .ASM .C b0bset key_bibi_f mov a,#0f0h mov menu_disp_h,a mov a,#00h mov menu_disp_l,a mov a,#11111111b mov disp5,a key_bibi_f = 1; menu_disp_h = 0xf0U; menu_disp_l = 0; disp5 = 0xffU;

通过判断条件P是否成立来选择A或B进行操作 2017/3/22 判断分支结构 判断分支结构的流程 P为真? A操作 B操作 通过判断条件P是否成立来选择A或B进行操作

判断分支结构的实现对比 .ASM .C cmprs a,#0ah nop b0bts0 fc jmp $+3 b0mov a,y ret 2017/3/22 判断分支结构的实现对比 .ASM .C cmprs a,#0ah nop b0bts0 fc jmp $+3 b0mov a,y ret add a,#6h if(result_buf > 0x0a) { result_buf = input + 6; } else result_buf = input;

这就是多级判断分支组合,想想它们又都是怎么实现的呢? 2017/3/22 串行分支结构 串行分支结构流程 P1为真? P2为真? Pn为真? C1 C2 C3 Cn N Y 这就是多级判断分支组合,想想它们又都是怎么实现的呢?

C用if,else if嵌套来实现串行分支结构 2017/3/22 串行分支结构实现对比 .ASM .C Buzzer00: b0bts1 P1 jmp buzzer10 …… jmp buzzer40 buzzer10: b0bts1 P2 jmp buzzer20 buzzer20: if(P1){ } else if(P2){ else if(Pn){ …… } C用if,else if嵌套来实现串行分支结构

并行分支结构其实是一个条件判断有多种可能,这又如何实现呢? 2017/3/22 并行分支结构 并行分支结构流程 P=? A1 A2 A3 An P=1 P=2 P=3 P=n 并行分支结构其实是一个条件判断有多种可能,这又如何实现呢?

并行分支结构实现对比 .ASM .C C可以用switch…Case来实现 mov a,step b0bts1 fz Jmp ks82 2017/3/22 并行分支结构实现对比 .ASM .C mov a,step b0bts1 fz Jmp ks82 cmprs a,ONE_PRESS_C Jmp ks83 cmprs a,TWO_PRESS_C Jmp ks84 cmprs a,BESPOKE_ING_C Jmp ks85 cmprs a,SELECT_TIME_C Jmp ks86 switch(step) { case 0: ks81();break; case ONE_PRESS_C: ks82();break; case TWO_PRESS_C : ks83();break; case BESPOKE_ING_C : ks84();break; …… } C可以用switch…Case来实现

2017/3/22 循环结构1——While While循环流程 A P为真? Y N 先判断,后执行!

While循环实现对比 .ASM .C tempbuf = 0; while(tempbuf==15) { ++tempbuf; } 2017/3/22 While循环实现对比 .ASM .C Clr y Loop: B0mov a,y Cmprs a,#15 Jmp $+2 Jmp loop90 decms y jmp loop loop90: RET tempbuf = 0; while(tempbuf==15) { ++tempbuf; } 编译器的转换并非和我们的比较代码一样

2017/3/22 循环结构2——do…while循环 Do…while循环流程 A P为真? Y N 先执行,后判断!

Do…while循环在编译器的转换中具有最高的效率 2017/3/22 Do…while循环实现对比 .ASM .C ClrRAM: clr Y b0mov Z,#0x7f ClrRAM10: clr @YZ decms Z jmp ClrRAM10 clr @YZ mov a,#00H unsigned int * pyz = (unsigned int *)0x7f; do{ *pyz = 0x00; --i; }while(i); Do…while循环在编译器的转换中具有最高的效率

2017/3/22 函数 函数的定义 函数参数的传递 函数参数与全局变量

函数的定义 SN8 C 函数声明方式: 返回值类型 函数名(形参1数据类型,形参2数据类型,……); 在C当中,函数都应该先声明,后调用 ! 2017/3/22 函数的定义 SN8 C 函数声明方式: 返回值类型 函数名(形参1数据类型,形参2数据类型,……); 在C当中,函数都应该先声明,后调用 ! 如: unsigned int bcd(unsigned int);

函数的定义方式 函数定义方式: 返回值类型 函数名(参数列表) 参数类型表; { 函数体; } Note: 2017/3/22 函数的定义方式 函数定义方式: 返回值类型 函数名(参数列表) 参数类型表; { 函数体; } Note: 对于无返回值的函数,都要声明是void,以免系统为其预留空间! 仅在传统格式当中出现

函数参数传递与返回 函数调用是通过参数传递和返回来传递数值 clock_min = bcd(clock_min); 2017/3/22 函数参数传递与返回 clock_min = bcd(clock_min); 函数调用是通过参数传递和返回来传递数值 unsigned int bcd(unsigned int input) { … … … return(result_buf); }

函数传递的内部实现 _callee_arg ? ; ? 为参数个数。 2017/3/22 函数传递的内部实现 假设于caller函数内调用callee函式. callee 的参数名称为: _callee_arg ? ; ? 为参数个数。 例如: int foo(int a, int b, long c) 会产生 _foo_data SEGMENT DATA INBANK ;OVERLAYABLE _foo_arg0 DS 1 ; int a _foo_arg1 DS 1 ; int b _foo_arg2 DS 2 ; long c 这些都由系统来完成!

实际参数clock_min被直接赋值给函数的形参_bcd_arg0,然后在调用函数中参加运算。最后返回值是在A中得到的 。 2017/3/22 函数参数传递实现对比 .ASM .C MOV A, (_clock_min) __SelectBANK _bcd_arg0 MOV _bcd_arg0, A ;End push arg.... call _bcd __SelectBANK (_clock_min) MOV _clock_min, A clock_min = bcd(clock_min); 实际参数clock_min被直接赋值给函数的形参_bcd_arg0,然后在调用函数中参加运算。最后返回值是在A中得到的 。

返回值的存放 返回值类型 寄存器 unsigned/signed char A unsigned/signed short 2017/3/22 返回值的存放 返回值类型 寄存器 unsigned/signed char A unsigned/signed short unsigned/signed int unsigned/signed long A,R float A,R,Y,Z 返回值是数据结构的,系统则会在调用函数的时候增加一个隐含参数(地址)传递给被调函数,被调函数在完成功能运算后将结果放到指定的位置上,程序从函数里返回后就可以从该地址读取返回值。

2017/3/22 尽管从原理上看起来,函数的参数传递与返回值的C与汇编的转换的形式是一样的,但是编译器产生代码时依然可能产生一些冗余代码。所以,在面对单片机这样的资源的硬件编程,过多的参数传递及过于复杂的返回值往往造成代码转换的低效率,这是用户需要注意的。

对于面对硬件的单片机编程,我们还是建议多用全局变量来传递数值,而不是用参数 。 2017/3/22 全局变量与函数参数 全局变量 函数参数 贴近汇编的形式,产生代码的效率高。 变量关联性高,模块化,可维护性,封装性差。 模块化,可维护性,封装性好。 存在数据传递的环节 ,更增加了转换的代码量。 对于面对硬件的单片机编程,我们还是建议多用全局变量来传递数值,而不是用参数 。

2017/3/22 构造数据类型 结构体 联合体

结构体的定义 结构体定义的形式: Struct 结构体类型名{ 成员1数据类型 成员1名称; 成员2数据类型 成员2名称; …… }; 2017/3/22 结构体的定义 结构体定义的形式: Struct 结构体类型名{ 成员1数据类型 成员1名称; 成员2数据类型 成员2名称; …… }; 例如: Struct structType{ Unsigned int memb1; Unsigned long memb2; Float memb3; };

结构体在存储形式上是按定义形式的先后,将成员逐个存储摆放形成一个数据块。 2017/3/22 结构体存储形式 结构体存储 memb1 memb2 memb3 结构体在存储形式上是按定义形式的先后,将成员逐个存储摆放形成一个数据块。

用结构体定义位域 位域的定义形式: Struct 结构体名称{ Unsigned bit0:1; Unsigned bit1:2; 2017/3/22 用结构体定义位域 位域的定义形式: Struct 结构体名称{ Unsigned bit0:1; Unsigned bit1:2; Unsigned bit2:1; Unsigned bit3:1; Unsigned num:4; }; 成员数据类型都是Unsigned。 冒号后面的数据是指占用位的数量,如成员bit1会占用2个bit 。

2017/3/22 结构体定义的限制 对于struct,我们只能对其实例安排存放的空间,加__RAM和__ROM限制字加于限制。而对于struct的成员我们就无法对其进行限制,这个原因是非常明显的,若是都允许对存放空间进行限制的话,就会造成冲突。如下定义是系统不允许的: struct StuType { int __ROM data; // 错误 };

联合体的定义 定义一个联合类型的一般形式为: union 联合名 { 成员表 }; 2017/3/22 联合体的定义 定义一个联合类型的一般形式为: union 联合名 {  成员表 }; 例如: union perdata { int memb1; long memb2; float memb3; };

在“联合”中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。事实上是同一个空间通过不同的名称调用 。 2017/3/22 联合体的存储形式 联合体的存储 memb1 memb2 memb3 在“联合”中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。事实上是同一个空间通过不同的名称调用 。

联合体在程序中的应用 将一个Long型数据与两个int型数据的结构体组成Union,如: 2017/3/22 联合体在程序中的应用 通过定义longType 的实例,我们就可以既对一个long型数据进行操作,又可以对数据的高低字节进行操作,既兼顾了C的方便特性,又能有汇编的灵活性。 将一个Long型数据与两个int型数据的结构体组成Union,如: union longtype { unsigned long longV; struct inttype unsigned int int_l; unsigned int int_h; }intV; };

2017/3/22 与struct一样,我们只能对UNION实例安排存放的空间,加__RAM和__ROM限制字加于限制。而对于union的成员我们就无法对其进行限制。

2017/3/22 中断 中断函数的定义 中断过程的分析 中断函数的结构

__interrupt MyHandler () { .... } 2017/3/22 中断函数的定义 中断函数声明方式如下: __interrupt MyHandler () { .... } 这是一个SN8 C专有的函数,用关键字__interrupt 来声明。__interrupt关键字(以两个底线开头)指示函数是要作中断向量的处理函数。 中断向量函数是一个无参数, 也无返回值的特殊函数。 中断向量进入点会备份所有寄存器,中断向量结束前, 前述备份的项目均会被还原。这些都是由编译器内部完成的。

2017/3/22 中断过程分析 程序在主循环中运行到①的时候,中断条件成立,系统产生中断,此时,系统将会去执行中断程序。而为了能从中断中正确返回,在进入中断程序之前,系统会对当前的状态(ACC,PC等等)进行保存。然后,在②处程序运行进入中断程序,③处中断程序结束,系统又需要将原来的运行状态还原,然后在④处继续运行主循环程序。一次中断完成。 ① ② ③ ④

中断函数的结构 建议对中断程序作这样的安排 Y N 中断1处理程序 中断2处理程序 中断3处理程序 中断n处理程序 RETI 2017/3/22 中断函数的结构 是中断1? 是中断2? 是中断3? 是中断n? Y N 中断1处理程序 中断2处理程序 中断3处理程序 中断n处理程序 RETI 建议对中断程序作这样的安排

2017/3/22 中断程序与主循环的关联 __interrupt intserv(void) { if(INTRQ&0x10) { _bCLR(&INTRQ,4); T0INT(); } else if(INTRQ&0x20) { _bCLR(&INTRQ,5); TC0INT(); … void TC0INT(void) TC0C=0x64; ftc0int = 1; void INTround(void) { unsigned int bitValue = 0; if(ftc0int) ftc0int = 0; fkeyTimer = 1; fflashTimer = 1; ThandDelay = 1; } … ... Void main(void) { …. INTround(); 为了使中断资源不被长时间占用,我们的中断程序内不能运行任何长时间占用系统时间的程序!其实占用中断资源的任务,我们完全可以安排到中断外去完成!我们只需要告诉主控程序发生了中断以及是哪个中断就可以了!

2017/3/22 位操作 位的定义 位的运算 位比较在程序流程控制中的应用

用户自定义位 Step1 Step2 Step3 位域的定义 : 定义一些具体的结构体实例: 2017/3/22 用户自定义位 Step1 Step2 位域的定义 : Struct bitDefine{ Unsigned bit0:1; Unsigned bit1:1; Unsigned bit2:1; Unsigned bit3:1; Unsigned bit4:1; Unsigned bit5:1; Unsigned bit6:1; Unsigned bit7:1; }; 定义一些具体的结构体实例: Struct bitDefine flag1,flag2,flag3; Step3 用宏定义的方法将我们需要的位名称赋予相对应的位。如: #define fkeypress (flag1.bit1) #define fchatfinish (flag1.bit2) #define fkeyProcessing (flag1.bit3) #define FhandDelay (flag1.bit4)

2017/3/22 位运算 对位的操作主要包含以下几种:置位,清除,位与(&),位或(|),位非(~),位异或(^),左移(<<),右移(>>)。 例如: Fkeypress = 1; //置位 Fkeypress = 0; //清除 keyinbuf <<=2; tempbuf = P0&0x03; keyinbuf |= tempbuf; keyinbuf = ~keyinbuf;

系统寄存器位操作函数 位操作函数原型 : 传入参数 address 与 bitOffset 必须为常数不可为变量。 2017/3/22 系统寄存器位操作函数 位操作函数原型 : void _bSET(unsigned long address, unsigned int bitOffset); void _bCLR(unsigned long address, unsigned int bitOffset); int _bTest0(unsigned long address, unsigned int bitOffset); int _bTest1(unsigned long address, unsigned int bitOffset); 传入参数 address 与 bitOffset 必须为常数不可为变量。 BitOffset 有效值为 0 ~7。 address 的高位为 bank number。

系统寄存器位操作 对系统寄存器进行位的置位和清除: _bSET(&TC0M,7); _bCLR(&TC0M,7); 系统转换的对应代码: 2017/3/22 系统寄存器位操作 对系统寄存器进行位的置位和清除: _bSET(&TC0M,7); _bCLR(&TC0M,7); 系统转换的对应代码: PreB0SET 218 7 0 PreB0CLR 218 7 0

三种方式产生的代码基本相同,第二种使用更方便。 2017/3/22 位比较在程序流程控制中的应用 系统寄存器的位判断可用以下3种方法: 1 用专用函数: if(_bTest1(&INTRQ,4)) { _bCLR(&INTRQ,4); T0INT(); } 用位运算的方法: if(INTRQ&0x10) { _bCLR(&INTRQ,4); T0INT(); } 3 三种方式产生的代码基本相同,第二种使用更方便。 2 用系统定义的位名称: if(FT0IRQ) { _bCLR(&INTRQ,4); T0INT(); }

2017/3/22 内嵌汇编 如何内嵌汇编 内嵌汇编时变量的传递

内嵌的汇编会被原样转换嵌入生成的汇编码当中 ! SN8 C 提供专门的关键字__asm(两个下划线)用于在C的源代码内嵌入汇编。 __asm关键词有以下两种用法: __asm(“code\n”) __asm { asm_text } 内嵌的汇编会被原样转换嵌入生成的汇编码当中 !

程序用“#pragma ref x”通知sn8cc, 变量x是有用到的! 内嵌汇编时变量的传递 “#pragma ref id”预处理指令 例如: void func(void) { int x; #pragma ref x __asm { … ;; 存取局部变量 x. } return; 程序用“#pragma ref x”通知sn8cc, 变量x是有用到的!

全局变量与内嵌汇编的传递 .C 生成代码档中的定义 原来它们将每一全局变量的前面都增加了一个“_”来标识它们! union flagWord2 { unsigned int flagByte; struct bitdefine2 unsigned bit0:1; unsigned bit1:1; unsigned bit2:6; }flagBit; }led_dp; unsigned int door_cnt; unsigned int door_cnt1; unsigned int door_cnt2; .stabs "led_dp:G43",32,0,0,_led_dp .stabs "door_cnt2:G14",32,0,0,_door_cnt2 .stabs "door_cnt1:G14",32,0,0,_door_cnt1 .stabs "door_cnt:G14",32,0,0,_door_cnt 原来它们将每一全局变量的前面都增加了一个“_”来标识它们! 在嵌入的汇编中,如果要读写全局变量,就在它们的前面加上一个“_”

SN8 C程序的结构组织 主函数与子函数 构建可复用文件 构建具有实用性的程序

任务的分时处理 对于整个程序而言,安排好main()函数对其他子函数的调用起着至关重要的作用。我们知道,大多任务我们没法在1毫秒内完成,有的甚至需要很长时间的延时,而在很短的时间内环境有可能发生改变,外部可能产生很多个请求。怎么样让程序既能完成任务(响应)又能及时接受外部请求及时处理? 我们把所有的任务都分别用一个标志位来标示他们是不是完成,对于完成的任务会产生什么样新的需求也用一个标志来标识它。而对于正在进行的任务我们每次只去完成应该完成的一部分,将这些正在完成的任务轮换进行处理直到完成。改换这一思想是实现我们的编程方案的关键。

我们可以将一个任务分为60或70次来完成,实现了分时实现。而很多占用很长时间的任务也都可以这么做。 传统按键扫描与分时按键扫描的对比 传统按键扫描 我们可以将一个任务分为60或70次来完成,实现了分时实现。而很多占用很长时间的任务也都可以这么做。 1 ① ② 分时按键扫描 2 ① ② …

程序层次结构图 任务队列 主控程序 功能1 功能2 功能3 功能n ……… 功能实现层 请求 响应、使能

程序结构可以分为任务排列层、主控层和功能实现层。 主控层依据功能实现层的请求标志设置来形成队列形成任务排列层,并对获取的请求安排响应和使能的优先顺序。然后读取FIFO里面的任务并发出使能和响应标志,主控层为系统的主循环,控制整个程序的运行,并且将通过设置响应和使能标志来调用功能实现层的子程序来实现功能。 任务排列层建立一个FIFO,FIFO里面存储系统标志位,按事件发生的顺序和主控程序的安排逐个地排列。 功能实现层为系统的功能程序(子程序),它由可复用的各种功能模块组成。在每个模块的开头进行程序判断,看是否需要执行程序或使能部分功能,并且在执行过程中,根据程序执行的结果对标志位进行置位,并返回给主控层,由主控程序安排响应!

实现层的子函数 程序主体 退出 执行程序的条件是不是成立? Yes No 在程序开头进行判断是否需要运行,若是条件没有满足或者没有接收到主控程序的使能信息,就直接跳转到程序结束,返回主控程序。而主控程序则每个循环(<1ms)都调用一次子程序进行查询!

对于全局变量我们可以通过在子程序文件中通过定义public型数据来实现程序的模块化。 构建可复用文件 #include <custom.h> Extern keyScan(); Extern keyInbuf; Extern keyChkbuf; Extern keyCvtbuf; Extern keyCode; … Void main(void) { keyScan(); } … Public keyScan(); Public unsigned int keyInbuf; Public unsigned int keyChkbuf; Public unsigned int keyCvtbuf; Public unsigned int keyCode; Void keyScan(void) { } 对于全局变量我们可以通过在子程序文件中通过定义public型数据来实现程序的模块化。

Thanks! 联系我: Phone:86-755-267196666-247 E-mail:dragon@sonix.com.cn