《单片机程序设计.pptx》由会员分享,可在线阅读,更多相关《单片机程序设计.pptx(29页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、单片机程序设计,单片机程序语言,机器语言 F2412034 (11110010100000010010000000110100) 汇编语言 MOVW R0,#0 x1234 C语言 register int a; a=0 x1234;,汇编语言,指令格式 标号: 操作码(助记符)操作数1,操作数2, MOVW R0,#0 x1234 指令周期 时钟周期(振荡周期)、机器周期、指令周期 指令长度,汇编语言寻址方式,立即寻址 a=5; 直接寻址 a=b0; 间接寻址 a=*p;,汇编语言,数据传送 算术逻辑运算 控制转移(跳转) 位操作 特殊,C语言开发的优势,加快开发进度。(尤其是复杂系统) 无
2、需精通单片机指令集合具体硬件。 可以实现软件的结构化编程。 省去了人工分配单片机资源(寄存器、RAM)的工作。 易于移植。 编译器可以自动实现中断服务程序的现场保护和恢复。可以自动生成一些硬件的初始化代码。 对复杂的系统开发,可以通过移植实时操作系统来实现。,C语言模块划分,模块即是一个.c文件和一个.h文件的结合。 头文件(.h)中是对于该模块接口的声明; 某模块提供给其它模块调用的外部函数及数据需在.h中文件中冠以extern关键字声明; 模块内的函数和全局变量需在.c文件开头冠以static关键字声明; 永远不要在.h文件中定义变量! 定义变量和声明变量的区别在于定义会产生内存分配的操作
3、,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其它模块寻找外部函数和变量。,只在文件内有效,C语言内存关键字指针,数据指针 int *p = (int *)0 xF000FF00; 对I/O口寄存器操作 对flash,ram存储器中的内容操作 函数指针 函数放在指定的地址空间 typedef void (*lpFunction) ( ); /*定义一个无参数、无返回类型的函数指针类型*/ lpFunction lpReset = (lpFunction)0 xF000FFF0; /*定义一个函数指针指向*/ lpReset(); /*调用函数*/,C语言内存关键字const,
4、const int table=1,2,3; /table表格只分配进程序存储器中 const char *ptr1 (指向常量的指针) 指针位于数据存储器空间指向程序存储器空间的字符型数据 char *const ptr2 (指针常量) 指针位于程序存储器空间指向数据存储器空间 const char *const ptr3 /指针位于程序存储器空间指向程序储存器空间,C语言内存关键字 volatile,volatile变量 优化,C语言内存,volatile int a volatile变量可能用于如下几种情况: 并行设备的硬件寄存器(如:状态寄存器,例中的代码属于此类) 一个中断服务子程序
5、中会访问到的非自动变量(也就是全局变量) 多线程应用中被几个任务共享的变量。,单片机程序结构,单片机程序结构,单片机程序结构,void main() sysinit(); moduleInit(); while(1) if(!ADTimer) ADTimer=500; 处理AD数据; if(!KeyTimer) KeyTimer=10; 扫描按键; ,if(!LEDTimer) LEDTimer=2; 扫描LED; if(hp!=rp) 处理串行接口数据; ,单片机程序结构,void SysTick_Handler() if(ADTimer) ADTimer-; if(KeyTimer) Ke
6、yTimer-; if(LEDTimer) LEDTimer-; ,时间片轮询法架构,1.设计一个结构体: /任务结构 typedef struct _TASK_COMPONENTS uint8Run; /程序运行标记:0-不运行,1运行 uint8Timer;/计时器 uint8ItvTime;/任务运行间隔时间 void(*TaskHook)(void);/要运行的任务函数 TASK_COMPONENTS;,时间片轮询法架构,2.任务运行标志出来,此函数就相当于中断服务函数,需要在定时器的中断服务函数中调用此函数,这里独立出来,并于移植和理解。 voidTaskRemarks(void)
7、uint8i; for(i=0;iTask_Max;i+)/逐个任务时间处理 if(TaskCompsi.Timer)/时间不为0 TaskCompsi.Timer-;/减去一个节拍 if(TaskCompsi.Timer=0)/时间减完了 TaskCompsi.Timer=TaskCompsi.ItvTime; /恢复计时器值 TaskCompsi.Run=1;/任务可以运行 ,时间片轮询法架构,3.任务处理,主程序中调用 voidTaskProcess(void) uint8i; for(i=0; iTASKS_MAX;i+) /逐个任务时间处理 if(TaskCompsi.Run) /时
8、间不为0 TaskCompsi.TaskHook();/运行任务 TaskCompsi.Run=0;/标志清0 ,时间片轮询法架构,4.应用建立任务 staticTASK_COMPONENTSTaskComps= 0,1000,1000,TaskDisplayClock,/显示时钟 0,10,10,TaskKeyScan, /按键扫描 0,5,5,TaskLedScan, /动态刷新LED /可以继续添加任务。 ;,时间片轮询法架构,4.应用编写各个任务函数 void TaskDisplayClock() void TaskKeySan() void TaskLedScan() ,时间片轮询法
9、架构,4.应用编写主函数 void main(void) InitSys();/初始化 while(1) TaskProcess();/任务处理 ,按键扫描程序,unsigned char read_key(void) unsigned char key_press; /按键是否被按下 unsigned char key_return = 0;/按键返回值 key_press = key_sr1; / 读按键I/O电? if(!key_press) delay(10); key_press = key_sr1; / 读按键I/O电? if(!key_press) key_return = 1;
10、 ,状态机按键扫描程序,按键初始状态,按键按下状态,按键释放状态,I/O口低电平,I/O口高电平,I/O口高电平,I/O口低电平,I/O口低电平,I/O口高电平,执行按键动作,按键扫描程序,/* 名 称:状态机按键扫描 功 能:运用状态机思想,实现按下按键LED点亮,再按一下LED灯熄灭。 作 者: 创建时间:2014年12月14日 修改时间: 备 注: */ #include /头文件 #includeKey_State.h /按键扫描头文件 sbit Led = P07; /LED灯输出 unsigned char Key_Number = 0; /按键值,按键扫描程序,/* 函数名称:主
11、程序 功 能:程序执行的入口 返 回 值:无 时 间:2014-12-14 备 注: */ void main() while(1) if(!Key_Timer) Key_Timer=10; /在定时器内每1Ms增1 Key_Number = read_key(); /按键扫描函数,取得按键值,10MS调用一次 if(Key_Number = 1) /按键返回值是1 Led = Led; /LED灯取反 ,按键扫描程序,Key_State.c #include sbit key_sr1 = P16;/ 按键输入口 #define key_state_0 0 /按键的初始状态 #define k
12、ey_state_1 1 /按键按下的状态 #define key_state_2 2 /按键释放的状态,按键扫描程序,/* 函数名称:按键扫描程序 功 能:检测按键,并返回按键值 返 回 值:key_press 时 间:2014-12-14 备 注: */ unsigned char read_key(void) static char key_state = 0; /按键的状态 unsigned char key_press; /按键是否被按下 unsigned char key_return = 0;/按键返回值 key_press = key_sr1; / 读按键I/O电? switc
13、h (key_state) return key_return; /返回按键值 ,按键扫描程序,switch (key_state) case key_state_0: / 按键初始态 break; case key_state_1: / 按键确认态 break; case key_state_2: /按键释放的状态 break; ,按键扫描程序,case key_state_0: / 按键初始态 if (!key_press) key_state = key_state_1;/ 键被按下,状态转换到键确认态 break; case key_state_1: / 按键确认态 if (!key_press) key_return = 1; / 按键仍按下,按键确认输出为“1” key_state = key_state_2;/ 状态转换到键释放态 else key_state = key_state_0; / 按键已抬起,转换到按键初始态 break; case key_state_2: if (key_press) key_state = key_state_0;/按键已释放,转换到按键初始 break; ,