




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、编程综述单片机编程其实就是对寄存器的操作,更多的是用流程控制语句来决定寄存器对应行为的先后时间顺序。什么时候该让寄存器干什么,什么时候停止。Keil-c 也可以使用指针来定义字符串。uchar *trdata="hello,RS232n"send_char(trdatai);unsigned char *puchMsg ;while (usDataLen-) /* 传输消息缓冲区*/uIndex = uchCRCHi *puchMsg+ ;while(TI=0);/直到TI=0才往下执行。尽量在子程序中少用while(1) /死循环。void sendchar(void)w
2、hile(1) /死循环。if(RI)/如果接收到数据。RI = 0;/软件清0dat = SBUF;/将接收到的数据赋给之前定义的变量。SBUF = dat;/将接收到的数据又发送出去。while(!TI);/ 等特数据传送, 查询是否发送完毕。TI = 0;/对发送标志位清0。当其他程序调用sendchar(void)时将不能跳出死循环,所以在写子程序时要严格使用死循环。标志位、控制位的对应一般将标志位作为判断条件来执行对应程序。结合中断使用的频率较高。例如SendFlag = 0就必须有对应置1的条件,而控制位更是要有对应的切换过程。例如RS485E=1; / RS5485E=0为接收状
3、态 RS5485E=1为发送状态if(TI = 1) TI = 0;SendFlag = 0; if(RI = 1) /RI接受中断标志 RI = 0; /清除RI接受中断标志Data = SBUF; /SUBF接受/发送缓冲器 SendFlag = 1; if (SendFlag=1) / 如果中断程序响应了,即就是单片机接收到数据这时就将接收到的数据进行回显,发送到PC RS485E=1; / RS5485E=0为接收状态 RS5485E=1为发送状态 SBUF=Data; /发送数据 delay(50); else RS485E=0; /接收状态 TM1629地址写的不对导致显示字符不对
4、。display2( 0xc0, LED14Num0);display2( 0xc1, LED14Num1);display2( 0xc2, LED14Num2);display2( 0xc3, LED14Num3);往后在编程过程中一定要注意写地址命令的地址格式。TM1629数码管字符显示乱码const unsigned char LED14Num=/ Number Encode0xa1,/ 0 LSB0x07,/ 0 MSB0x01,/ 1 LSB0x01,/ 1 MSB0x4A,/ 2 LSB0x1C,/ 2 MSB原因就在于焊接数码管引脚时没有按照顺序来,而导致编码没办法进行统一编码。
5、下次可以根据编码推理出管脚位置然后再焊接引脚。I+导致的编码错误switch(*pt) case '0': disdatai =LED14Num0;disdatai+1 =LED14Num1; break; case '1': disdatai =LED14Num2;disdatai+1 =LED14Num3; break;i+;导致每次显示都会将i+1覆盖;i+1和i+重复了。改为i=i+2;小数点的错位 for(k=0;k<6;k+) if(disdataj=LED14Num7) display2( LED_GRIDj-2, 0x40|disdataj
6、-2) ;k=j-1;j+;/让下一个数据得到正确显示。 display2( LED_GRIDk, disdataj); j+; 在没有小数点时要显示的数据正好和显示的位置对应但一旦有了小数点则将会使要显示的数据和显示的位置错了一位,所以选择k,j两个变量来进行位和数据的选择。注意j+;/让下一个数据得到正确显示。的位置。对寄存器的操作进行打包成为固定函数,直接对该函数进行调用#define PORT_KEY1 (PTC_BASE_PTR)#define PIN_KEY1 (5u)#define KEY1_OUTPUT() (PORT_KEY1->PDDR |= SHIFT_DATA &
7、lt;< PIN_KEY1)#define KEY1_INPUT() (PORT_KEY1->PDDR &= (SHIFT_DATA << PIN_KEY1)#define KEY1_HIGH() (PORT_KEY1->PSOR |= SHIFT_DATA << PIN_KEY1)#define KEY1_LOW() (PORT_KEY1->PCOR |= SHIFT_DATA << PIN_KEY1)#define KEY1_TOG() (PORT_KEY1->PTOR |= SHIFT_DATA <<
8、PIN_KEY1)#define KEY1_STATE() (PORT_KEY1->PDIR & (SHIFT_DATA << PIN_KEY1)#define KEY1_CONFIG_PTR (PORTC_PCR5)#define KEY1_FUNC_CFG(fun) (KEY1_CONFIG_PTR &= PORT_PCR_MUX_MASK, KEY1_CONFIG_PTR |= fun << PORT_PCR_MUX_SHIFT)将某一功能用一个变量来实现,jiffies+; 实现1ms自加功能void FTM0_IRQHandler(voi
9、d) /定时中断服务函数static u32 jbak = 0;TIMER_1MS_CLR_FLAG(); /清零jiffies+; /变量值增加 msif(_pasti(jbak)>60000)Minutes_count+;jbak=jiffies; /Minutes将固定的简单运算用宏定义来实现#define _pasti(jbak)(u32)(jiffies - jbak)将要包含的头文件建立成一个总的头文件,其他文件只用包含这个总的头文件其他文件包含#include "derivative.h"derivative.h为以下内容/* Include the d
10、erivative-specific header file */#include <null.h>#include <stdlib.h>#include <MKL15Z4.h>#include "public.h"Extern用法extern enum enum_menu_step menu_step;extern enum enum_menu_step limit_screen;将enum_menu_step对外输出menu_step和limit_screen相当于起了两个别
11、名。extern void menu_proc(void);让menu_proc函数可以被其他文件的函数调用有两种用法:1. 在本.H中进行extern声明,然后在其他.h中包含本.H(只在本.h中声明对外要用的东西)2. 在其他.h中声明来源于其他文件的extern变量,这样其他.h中就不用包含本.H建议使用第一种用法减少变量重复声明,改动变量类型时无需大范围查找。51单片机关键字SFR51单片机关键字SFR用于定义特定功能专用寄存器,编译器会把SFR定义的寄存器使用直接访问方式访问,如果不定义后定义为普通变量,51编译器访问的是通用寄存器,应为51单片机的专用寄存器与部分通用寄存器地址空间
12、重叠(80H-FFH)。Char 型和int型用于延时程序延时区别很大。不管你使用哪种进制来传输数据计算机最终都会转化为2进制来处理。P0=255和P0=0xff没有区别。通过移位运算来实现不同类型数据的传输。unsigned long l;unsigned int m,n;while(1)l=65280; /ff00m=l>>8;/l的高8位 ffP0=m; delay(500);n=l; /l的低8位00,高8位没地方存P0=n;delay(500);指针数组unsigned char code str3 ="The Systerm is designed by Zh
13、angSan"unsigned char code str4 ="The date is 2008-9-30"unsigned char *p =str1,str2,str3,str4; /定义p4为指向4 个字符串的字符型指针数组void led_display(unsigned char *x ) /形参必须为指针数组unsigned char i,j;for(i=0;i<4;i+) /有4 个字符串要显示j=0; /指向待显字符串的第0 号元素while(*(xi+j)!='0') /只要第i 个字符串的第j 号元素不是结束标志P0=*
14、(xi+j); /取得该元素值送到P0 口显示delay(); /调用延时函数j+; /指向下一个元素结构体指针的访问struct tm int tm_sec; /* seconds after the minute, 0 to 60 (0 - 60 allows for the occasional leap second) */ int tm_min; /* minutes after the hour, 0 to 59 */ int tm_hour; /* hours since midnight, 0 to 23 */ int tm_mday; /* day of the month,
15、 1 to 31 */ int tm_mon; /* months since January, 0 to 11 */ int tm_year; /* years since 1900 */ int tm_wday; /* days since Sunday, 0 to 6 */ int tm_yday; /* days since January 1, 0 to 365 */ int tm_isdst; /* Daylight Savings Time flag */ union /* ABI-required extra fields, in a variety of types */ s
16、truct int _extra_1, _extra_2; ; struct long _extra_1_long, _extra_2_long; ; struct char *_extra_1_cptr, *_extra_2_cptr; ; struct void *_extra_1_vptr, *_extra_2_vptr; ; ;struct tm *time_now;void time_receive_display(void)char *buff_tim;/如果指针不行就改为数组,char buff_tim20; tim_c=tim_it+SEC_counter;time_now=l
17、ocaltime(&tim_c); RTC_FLAG=0;sprintf(buff_tim,"%02d:%02d",(*time_now).tm_hour,(*time_now).tm_min);display_auto_hanzi(0,88,float_display,buff_tim);结构体指针的访问是先访问整个结构体然后在指向结构体的某个元素。后来代码修改后不能直接访问结构体变量,引入中间变量后就可以了。猜测原因可能是增加代码后结构体指针发生了变化。软件字符编码不同解码出的数据也不同例如串口调试助手解码是以ASCII码来解析的,当你发送一个十进制数33时它会
18、解析成!而不是数字33.While(!TI);等待TI为1时往下执行。While();中值为假时往下执行。While()()中值为真时执行中的语句。Sprintf格式化输出sprintf(s, "%f",per_current_val);将per_current_val变量以字符串格式输出到char* s;注意不支持浮点数据的单片机sprintf不能格式化输出float型变量。sprintf(s, "%02d",per_current_val);如果per_current_val不够2位则在前面补0.参数匹配问题例如以下程序U16 val ;s8 buf
19、10;sprintf(buf, "%01d.%03d",adc_val/10000, adc_val%10000);以上代码总是报错,分析sprintf()函数应该不会错,可能就是传的参数有问题,然后进行立即数传送则正确,证明这个分析,最后考虑是参数类型不匹配short与int做除法,还没进行强制转化,后来加上强制转化就OK了。/sprintf(buf,"%01d.%03d",12/12,13%14);sprintf(buf,"%1d.%d",(u16)(adc_val/10000),(u16)(adc_val%10000);led_
20、disp_str(buf);将BCD码变为十进制/将BCD码变为十进制,如将0x23变为23/注意:高四位和低四位均不能大于9#define BCD_TO_DECIMAL(bcd) (BYTE)(BYTE)(bcd) >> 4) * 10 + (BYTE)(bcd) & 0x0f)#define DECIMAL_TO_BCD(decimal) (BYTE)(BYTE)(decimal) / 10) << 4) | (BYTE)(decimal) % 10)通过枚举建立同一类型数据,并初始化enum enum_menu_list MENU_set_sp1_dela
21、y=1, MENU_set_sp1_open_point, MENU_set_sp2_delay, MENU_set_sp2_open_point, MENU_set_sp3_delay, MENU_set_sp3_open_point, MENU_set_sp4_delay, MENU_set_sp4_open_point, MENU_set_sp5_delay, MENU_set_sp5_open_point;这样会便于识别各个参数意义以及程序的整体阅读。比如switch(const_pub_context_factory.point)case MENU_set_sp1_delay:spr
22、intf(lcd_dsp.dsp_buf,"SL.L:-%04d",temp);break;case MENU_set_sp1_open_point:sprintf(lcd_dsp.dsp_buf,"SL.L:-%03d.%01d",temp/10, temp%10);break;用枚举来建立菜单首先用枚举来建立菜单以备调用enum enum_menu_step MENU_IDLE_SLEEP, /低功耗界面 MENU_IDLE_SLEEP_3, /通信状态 -CP- / 6Pr5 /主界面 可实现6路的切换显示 MENU_DSP_PWD_ERR, ME
23、NU_SET_PWD, /一级菜单 MENU_DSP_ADDRESS, /客户模式为通讯地址 厂家模式为 设备号 MENU_DSP_DATE,/二级菜单 MENU_DSP_ROAD_CHIOCE, MENU_SET_RETURN_FACT, /三级菜单 MENU_DSP_ROAD_ABLE, MENU_DSP_ROAD_UNABLE,;建立菜单程序void menu_proc(void) menu_key_proc();/调用菜单按键程序void menu_key_proc(void)void menu_key_proc(void) s32 lcd_temp;u32 temp;static u
24、32 screen_delay = 0; if (key_set_click&&!key_up_click&&!key_down_click) key_set_click = false; menu_key_set_proc(); else if (key_up_click&&!key_set_click&&!key_down_click) key_up_click = false; menu_key_up_proc(); else if (key_down_click&&!key_set_click &&
25、amp;!key_up_click) key_down_click = false; menu_key_down_proc(); else key_down_click = false; key_up_click = false; key_set_click = false; if(_pasti(screen_delay)>300) screen_delay=jiffies; switch (menu_step) case MENU_IDLE_SLEEP: GPRS_LCD_CLEAR(); GPRS_LCD_OFF(); break; case MENU_IDLE_SLEEP_3: c
26、ase MENU_IDLE_SLEEP_1: case MENU_IDLE_SLEEP_2: if (_pasti(jkey_idle) >5000) jkey_idle=jiffies; menu_step = MENU_IDLE_SLEEP; break;void menu_key_set_proc()void menu_key_set_proc() u32 temp = 0; s32 s_temp=0; switch(menu_step)case MENU_IDLE_SLEEP:GPRS_LCD_INIT();/menu_step=MENU_IDLE_1; if(pub_conte
27、xt.Road1_En_Sign=ROAD_EN_SIGN)menu_step=MENU_IDLE_1; else if(pub_context.Road2_En_Sign=ROAD_EN_SIGN)menu_step=MENU_IDLE_2; else if(pub_context.Road3_En_Sign=ROAD_EN_SIGN)menu_step=MENU_IDLE_3; else if(pub_context.Road4_En_Sign=ROAD_EN_SIGN)menu_step=MENU_IDLE_4; else menu_step=MENU_IDLE_5; break;数组数
28、据处理程序char tty_tx_bufTTY_TX_SIZE;#define TTY_TX_SIZE 100#define tty_tx_incp(pt, n) do pt += n; if (pt>tty_tx_buf+TTY_TX_SIZE) pt -= TTY_TX_SIZE; while(0)tty_tx_incp(tty_tx_tail, 1);/发送完毕后将发送缓冲区指向开始位置以上程序可以在发送数组数据到最后一位时将数组指向首位,从而方便下一次读写。单片机C语言code与data的作用code的作用是告诉单片机,我定义的数据要放在ROM(程序存储区)里面,写入后就不能再更
29、改,其实是相当与汇编里面的寻址MOVC(好像是),因为C语言中没办法详细描述存入的是ROM还是RAM(寄存器),所以在软件中添加了这一个语句起到代替汇编指令的作用,对应的还有data是存入RAM的意思。code区在运行的时候是不可以更改的,data区放全局变量和临时变量,是要不断的改变的,code区存储在什么介质上并不重要,象以前的计算机程序存储在卡片上,code区也可以放在rom里面,也可以放在ram里面,也可以放在flash里面(但是运行速度要慢很多,主要读flash比读ram要费时间),因此一般的做法是要将程序放到flash里面,然后load到 ram里面运行的;DATA区就没有什么选择
30、了,肯定要放在RAM里面,放到rom里面改动不了。 data -> 可寻址片内ram bdata -> 可位寻址的片内ram idata -> 可寻址片内ram,允许访问全部内部ram pdata -> 分页寻址片外ram (MOVX R0) (256 BYTE/页) xdata -> 可寻址片外ram (64k 地址范围) code -> 程序存储区 (64k 地址范围),对应MOVC DPTR const 表示本数组不可修改 数组为常量数组中断程序注意事项void TMR0_ISR(void)/中断程序 / clear the TMR0 interrup
31、t flagINTCONbits.TMR0IF = 0;time+;主函数调用if(time=2) /100us time=0;此处判断最好用标志位来做,time_flag,因为程序在运行的过程中,中断程序很可能会相应,从而time将会在运行的过程中跳过time=2,主函数调用则会出现问题。硬件知识总结数码管测试在进行数码管共阴或共阳测试时直接用测导通的方法,因为导通档直接提供3mA左右的电流。ADC调试对管脚的正确配置,通道的正确选择,参考电压、基准电压的选取!(遇到调试无法采集数据,后来才发现是没有基准电压!)芯片封装QFN封装有0.65和0.5两种软件移植问题同一型号的CPU在不同的硬件
32、电路中使用的引脚各不相同,因此相应的软件配置也各不相同,从而导致即使一个软件没有涉及另一个硬件电路所使用的模块,引脚也没有使用,但这也不能保证其它配置功能对该电路的影响,而且这些底层的配置是不易被察觉到,从而造成不可控的影响,所以不可贸然将软件进行简单修改而放到另一硬件平台上。如果实在找不到相对应的硬件平台那么就只能自己去按模块单独调试。先观察现象,从理论上找问题所在,编辑代码是辅助手段 不要单纯修改代码主函数中其他函数时间分配(时间片的概念)在主函数中其他的函数尽量短时间的完成,不要出现while(1)这样的死循环,浪费资源不说,最重要的是可能会导致其他功能的失效,比如ADC的采集,更有甚者
33、会造成后续控制部分的失控,比如以下按键处理子程序会导致其他功能无法进行,但单片机外围器件仍在工作,将会导致外围失控。while(1)keyscan();if(k2=4)/按下+键const_pub_context_factory.out1_delay+;disp_sp1_delay_val();else if(k2=8)/按下-键const_pub_context_factory.out1_delay-;disp_sp1_delay_val();elsebreak;u32 TIMER_1MS_add(u32 jbak)u32 ms;jbak= jiffies;(严重错误)if(jiffies-
34、jbak)>0)ms=jiffies-jbak;elsems=65536-jbak+jiffies;return ms;void led_key_proc(void)s8 buf10;/s8 key_save_flag=0;/key_save_flag=0时s32 key_num=0;keyscan();if(k1!=0)|(k2!=0)|(k3!=0)|(k4!=0)|(k5!=0)/判断是否有键按下/if(k1!=0)&&(k2=0)&&(k3=0)|(k2!=0)&&(k1=0)&&(k3=0)|(k3!=0)&
35、;&(k2=0)&&(k1=0)/判断是否是独立按键/if(k1=1)/进行SP1延滞设置set_sp1_delay_menu();while(1)keyscan();if(k2=4)/按下+键const_pub_context_factory.out1_delay+;disp_sp1_delay_val();else if(k2=8)/按下-键const_pub_context_factory.out1_delay-;disp_sp1_delay_val();elsebreak;else if(k1=2)/进行SP1开关点设置set_sp1_open_point_me
36、nu();while(1)keyscan();if(k2=4)/按下+键const_pub_context_factory.out1_active_val+;disp_sp1_open_point_val();else if(k2=8)/按下-键const_pub_context_factory.out1_active_val-;disp_sp1_open_point_val();elsebreak;else if(k1=4)/进行SP1延滞设置set_sp2_delay_menu();while(1)keyscan();if(k2=4)/按下+键const_pub_context_facto
37、ry.out2_delay+;disp_sp2_delay_val();else if(k2=8)/按下-键const_pub_context_factory.out2_delay-;disp_sp2_delay_val();elsebreak;以下是时间片轮询的方式u8 key_value_scan(void)u16 key_temp,i;key_scan();if(get_key()!=0)&&(first_tip_flag=0)/new keyjbak =jiffies;first_tip_flag=get_key();else if(get_key()!=0)&
38、&(first_tip_flag!=0) /new to continue (or continue to continue)if(get_key()=first_tip_flag)&&(Con_tip_flag=0) /new to continueCon_tip_flag = first_tip_flag;else if(first_tip_flag!=0)&&(Con_tip_flag!=0) /continue to continueif(first_tip_flag = Con_tip_flag) /same key continue/judge delayif(TIMER_1MS_add(jbak) >60) /key value validfor(i=0;i<14;i+)key_temp=first_tip_flag>>1;if(key_temp&0x01)=1)i=i+2;brea
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 员工保密协议合同
- 矿权转让居间合同
- 房产出售委托协议书
- 旅游服务合作协议
- 公路工程投资合伙协议
- 人教版五年级下册数学求最大公因数练习300题及答案
- 铁肩中学门卫合同8篇
- 第1课 殖民地人民的反抗斗争(教学设计) 九年级历史下册同步高效课堂(部编版)
- 第十章 第4节 跨学科实践:制作微型密度计(教学设计)2024-2025学年度人教版(2024)物理八年级下册
- 房屋健康监测设备安装协议
- 2024年济南工程职业技术学院高职单招(英语/数学/语文)笔试历年参考题库含答案解析
- 癔症护理查房
- 骆驼祥子祥子成长经历
- 团队协作和领导力
- 奋力前行迎接挑战主题班会课件
- 红木家具通用技术条件解析
- 病毒性肺炎疾病演示课件
- 沃尔沃S60L 2014款说明书
- 汽车零部件喷漆项目分析报告
- 2023年2月对医疗机构的培训(新区医院版)
- 软星酒店网络规划与设计
评论
0/150
提交评论