OpenEdv-开源电子网

标题: 菜鸟开帖,持续更新90天,顺序学习开发板大部分实验,以此帖作为一个坚持的动力 [打印本页]

作者: 龙之谷    时间: 2015-7-21 23:48
标题: 菜鸟开帖,持续更新90天,顺序学习开发板大部分实验,以此帖作为一个坚持的动力
开帖原因:毅力不足,三天打鱼两天晒网,经常制定目标,但执行力不够强,用此帖记录90天的历程,督促自己踏踏实实的学习
学习板  :探索者STM32F4
起始时间:2015年07月22日
更新时间:每晚23:45前完成更新

目    标:90天时间完成开发板的大部分实验,不求快但求稳

买开发版也有一段时间了,如果踏踏实实学习现在实验也应该测试过半了,但经常好高骛远,基础不扎实,导致来回往复,故此指定时间为90天,留有一定裕量,希望静下心来一步一步前进,踏实是最快的路径。
如果有哪位坛友也有此意,欢迎加入,互相交流,共同进步。Now,Fighting!

楼主总结:
更新过程中虽存在很多问题:
1.更新内容既非原创,内容深度又不足;
2.更新内容长短参差不齐,受心情、当天内容影响,更新内容所用时长差异较大,一般在两个小时左右,一部分时长低于一个半小时;
3.更新顺序、整体环节不够顺畅、调理等等。
但仍希望置酷,觉得有个酷帖是蛮酷的一件事~~~~~

附件为目录excel和txt格式。

Thank you for your encouragement!

作者: 正点原子    时间: 2015-7-21 23:52
祝楼主早日登堂入室。
作者: 龙之谷    时间: 2015-7-22 08:25
回复【2楼】正点原子:
---------------------------------
谢原子哥鼓励。这冒号我发表前记得是对齐的,发表后还是跑偏了,这个略蛋疼。。。
作者: w417074951    时间: 2015-7-22 08:46
加油

帮顶
作者: 非洲小男孩    时间: 2015-7-22 09:53
加油,哥们。持之以恒的努力,终究会获得成功
作者: k_金先生    时间: 2015-7-22 13:26
我也是  那我们一起交流
作者: 西点    时间: 2015-7-22 15:36
坚持是成功它爸
作者: 龙之谷    时间: 2015-7-22 18:46
回复【4楼】w417074951:
---------------------------------
回复【5楼】非洲小男孩:
---------------------------------
谢谢 w417074951 和 非洲小男孩 两位坛友的鼓励
作者: 龙之谷    时间: 2015-7-22 18:48
回复【6楼】k_金先生:
---------------------------------
找到小伙伴了,握个手

希望共同进步,每天更新自己的进度,贵在坚持
作者: 龙之谷    时间: 2015-7-22 18:50
回复【7楼】西点:
---------------------------------
这样的话,坚持和失败是两口子,一家三口关系确定了,哈哈
作者: 龙之谷    时间: 2015-7-22 22:45
第〇一天:2015年07月22日  周三     例程:跑马灯实验

万事开头难,好在开发板前期的一部分实验难度不大,除了自身惰性,不会有太大阻力打击积极性。
跑马灯实验可谓开发板的迎宾人员,他帮我们打开芯片开发的大门。
探索者开发板跑马灯实验是操作两个指示灯,通过位带操作直接控制指示灯亮灭,今天在此例程基础上稍微迈进一步,使用函数将指示灯进行简单封装,一方面能够稍微简化以后的代码输入量,另一方面使程序模块化。添加函数如下
[mw_shl_code=c,true]/********************************************************************* 功能 :指示灯闪烁函数 //LedNum :动作小灯编号,0--LED0闪烁 1--LED1闪烁 2--LED0/LED1交替闪烁 3--据需扩展 //LightDelay:小灯点亮/交替闪烁 延时时长 //DarkDelay :小灯变暗/交替闪烁 延时时长 ********************************************************************************************/ void Led_Shine(uchar LedNum, uint LightDelay, uint DarkDelay) { if(LedNum == 0) { LED0 = 0; delay_ms(LightDelay); LED0 = 1; delay_ms(DarkDelay); } else if(LedNum == 1) { LED1 = 0; delay_ms(LightDelay); LED1 = 1; delay_ms(DarkDelay); } else if(LedNum == 2) { LED0 = 0; LED1 = 1; delay_ms(LightDelay); LED0 = 1; LED1 = 0; delay_ms(DarkDelay); LED0 = 1; //恢复默认状态小灯不亮,使显示达到预期 LED1 = 1; } else if(LedNum == 3) { ; //待扩展 } }[/mw_shl_code]

跑马灯实验主要知识点在于使能时钟后的GPIO口配置,故整理了一下原子哥配置函数中的参数表,见附件CheatSheet.txt

今日推荐:[分享]Keil编译后的Code,RO,RW,ZI分别表示什么以及和芯片Flash、SRAM的对应关系
坛友用简洁的语言把问题分析的清楚到位,很是佩服...


作者: 正点原子    时间: 2015-7-22 23:17
回复【11楼】龙之谷:
---------------------------------
不错
作者: 龙之谷    时间: 2015-7-23 23:09
第〇二天:2015年07月23日  周四     例程:蜂鸣器实验

1.硬件原理图
(, 下载次数: 419)
个人硬件基础不是很扎实,在此根据蜂鸣器配套视频及教程总结一下:R59与S8050构成电流放大电路,通过单片机引脚控制(大功率)蜂鸣器发声;R61则是为了避免IO口浮空状态导致蜂鸣器误发声,当有小电流时直接下拉到地,从而保证了蜂鸣器的稳定性。当IO口送高电平时三极管导通,蜂鸣器发声。

2.有源蜂鸣器与无源蜂鸣器主要区别
(, 下载次数: 370)
以前看书没注意到这段话,看书还是不够仔细,自省一下...


3.与指示灯相同,蜂鸣器也封装一下,但蜂鸣器在后续实验使用较少,代码量少封装起来意义不大,仅作为模块化的一种练习了
[mw_shl_code=c,true]/********************************************************************* 功能 :蜂鸣器模块控制模块 //SoundTime:发声延时时长 //QuietTime:静音延时时长 ********************************************************************************************/ void Beep_Play(uint SoundTime, uint QuietTime) { BEEP = 1; delay_ms(SoundTime); BEEP = 0; delay_ms(QuietTime); }[/mw_shl_code]

4.如果想进一步学习控制蜂鸣器,推荐
蜂鸣器基础知识及原理:http://www.hongyan-e.com/web/fmqyl.htm
蜂鸣器演奏及原理    :http://wenku.baidu.com/link?url=u8KN-1zyQ0_GpfGlMDDH5C_untMTnX6pMgroSU0g_J7SzpK0ubNPKa8nzb05geha_qA-ZfTKuvUx8uChAo_2FqfArNrhlPWg0lMDPiTYVB7
蜂鸣器音乐简谱转换工具:http://blog.163.com/likangbei@126/blog/static/141308394201311722922100/

今日推荐:STM32输入输出模式理解
文章对GPIO口的8中配置及用途进行了详细的讲解,对于困惑于此的人有很大帮助。

作者: jermy_z    时间: 2015-7-23 23:15
其实楼主可以把蜂鸣器响几声,响的时间和不响的时间做成参数,封装起来
作者: 正点原子    时间: 2015-7-23 23:25
mark...
作者: 龙之谷    时间: 2015-7-23 23:31
回复【14楼】jermy_z:
---------------------------------
确实,这样更完善了,多谢指导


/*********************************************************************
  功能  :蜂鸣器模块控制模块
//Count :蜂鸣器发声次数
//SoundTime:发声延时时长
//QuietTime:静音延时时长
********************************************************************************************/
void Beep_Times(uchar Count, uint SoundTime, uint QuietTime)
{
    uchar i = 0;

    for(i=0; i<Count; i++)
    {
        BEEP = 1;
        delay_ms(SoundTime);
        BEEP = 0;
        delay_ms(QuietTime);
   }

作者: 龙之谷    时间: 2015-7-23 23:33
回复【15楼】正点原子:
---------------------------------
原子哥,你mark什么啊,我这玩过家家的
作者: 正点原子    时间: 2015-7-24 00:02
回复【17楼】龙之谷:
---------------------------------
鼓励下你啊
看你能坚持多久,呵呵。
作者: 阿法尔大胡子    时间: 2015-7-24 00:09
前排占楼,顺便支持一下
作者: 龙之谷    时间: 2015-7-24 00:13
回复【18楼】正点原子:
---------------------------------
哈哈
作者: 龙之谷    时间: 2015-7-24 00:14
回复【19楼】阿法尔大胡子:
---------------------------------
谢谢支持,前排板凳已摆好
作者: ken1986    时间: 2015-7-24 10:33
mark....
作者: mingjie2015    时间: 2015-7-24 15:21
mark >>>>
作者: mingjie2015    时间: 2015-7-24 15:41
mark 支持一下
作者: 龙之谷    时间: 2015-7-24 16:12
回复【23楼】mingjie2015:
---------------------------------
回复【24楼】mingjie2015:
---------------------------------
这位mingjie2015朋友,连着mark两次是几个意思,哈哈

谢谢支持,祝好运
作者: ch_1964    时间: 2015-7-24 17:07
必须给顶一下,支持,鼓励
作者: jackieit    时间: 2015-7-24 17:57
mark12345
作者: 龙之谷    时间: 2015-7-24 19:36
回复【26楼】ch_1964:
---------------------------------
感谢支持...

回复【27楼】jackieit:
---------------------------------
678910,哈哈
作者: 龙之谷    时间: 2015-7-24 22:06
第〇三天:2015年07月24日  周五     例程:按键实验

1.支持连按:在原子哥教程中的含义是指,保持按键按下状态(持续20ms以上),按键多次响应,也就是按键起作用超过一次。在按键实验可以发现连按状态下按键控制指示灯和蜂鸣器,当松开按键时指示灯和蜂鸣器的状态并不是确定的,因为期间延时过短,我们无法控制响应次数。分析到此,我们可以通过增加延时时长来相对准确控制响应次数,比如中间添加五分钟延时供我们控制响应次数。大部分手机是支持连按的,它应该就是通过添加合适的延时以符合人们的使用习惯。
不支持连按:(支持连按的反义词),就是长时间按下按键,只响应一次。

2.我们可以在原子哥例程中支持连按状态时添加一个100ms延时供我们轻松观察到连按时按键多次触发带来的变化。
[mw_shl_code=c,true]static uchar key_up = 1; if(mode == 1) { key_up = 1; delay_ms(100); }[/mw_shl_code]

3.按键程序使用了IO口内部上下拉,对IO口的配置进行了合理的使用,这一点需要研究学习,如我者,GPIO配置0X3、0X8,如果需要上下拉会通过外接电阻实现,对内部上下拉感觉陌生不放心,皆是不够熟悉内部配置、使用较少所致,以后会注意使用。


------------------------------------隔一下--------------------------------------
按剧情发展,写到这就该来个今日推荐然后发送了,恰恰相反,刚刚开始,今天的今日推荐是没有了,如果想看的朋友们绕行了。下面的主题时printf和sprintf简单介绍及使用,昨天搜了一个多小时资料,其中包括我们论坛的分享与求助,现在时间2015年07月24日 20:53:48开始整理。
------------------------------------隔一下--------------------------------------

1.几个相关名词

重定向-----用户能定义自己的C语言库函数,连接器在连接时自动使用这些新的功能函数的过程叫做重定向C语言函数库。如本来库函数fputs()是把字符输出到调试器控制窗口中去的,但用户把输出设备改成了UART端口,这样一来,所有基于fput()函数的printf()系列函数输出都被重定向到UART端口上去了。

半主机-----用于 ARM 目标的一种机制,可将来自应用程序代码的输入/输出请求传送至运行调试器的主机。 例如,使用此机制可以启用 库中的函数,如 printf() 和 scanf(),来使用主机的屏幕和键盘,而不是在目标系统上配备屏幕和键盘。
这种机制很有用,因为开发时使用的硬件通常没有最终系统的所有输入和输出设备。 半主机可让主机来提供这些设备。半主机是通过一组定义好的软件指令(如 SVC)来实现的,这些指令通过程序控制生成异常。 应用程序调用相应的半主机调用,然后调试代理处理该异常。 调试代理提供与主机之间的必需通信。(这是坛友帖子里的,理解起来还是陌生,先搁这)

__align(num) ----- 这个用于修改最高级别对象的字节边界。在汇编中使用LDRD或者STRD时, 就要用到此命令__align(8)进行修饰限制。来保证数据对象是相应对齐。 这个修饰对象的命令最大是8个字节限制,可以让2字节的对象进行4字节 对齐,但是不能让4字节的对象2字节对齐。__align是存储类修改,他只修饰最高级类型对象不能用于结构或者函数对象。ADS环境下,“ALIGN 、“__align(x) 、“__packed”关键字用于字节对齐处理。ALIGN用于汇编语言,__align(x)用于C语言,__packed用于一字节对齐。   (注:有时候使用printf时出现HardFault_Handler中断,可能是字节对齐问题,定义的打印变量添加__align(4)或__align(8)有可能能够解决问题



2.下边这段代码,使用原子哥例程的都应该多多少少见过几次面,上面的铺垫目的正在于此。
[mw_shl_code=c,true]//加入以下代码,支持printf函数,而不需要选择use MicroLIB #if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; /* Whatever you require here. If the only file you are using is */ /* standard output using printf() for debugging, no file handling */ /* is required. */ }; /* FILE is typedef’ d in stdio.h. */ FILE __stdout; //定义_sys_exit()以避免使用半主机模式 _sys_exit(int x) { x = x; } //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1->SR&0X40)==0);//循环发送,直到发送完毕 USART1->DR = (u8) ch; return ch; } #endif [/mw_shl_code]
为什么重定向fputc后就能使用printf呢?在上边重定向中有了原理介绍,为求个心里踏实,在网上找printf函数原型,可能个人能力有限,没找到MicroLib库函数,C标准函数实现中printf是调用了putc()函数,不过以下图片这段话倒是说明printf调用了fputc函数,这样的话,重定向fputc后通过printf可以通过串口打印数据也就顺理成章了。(如果哪位大神看到这里并有printf调用fputc的函数原型请指导告知
(, 下载次数: 379)

3.printf(摘自百度百科)-----开发指南中多次使用,如printf(“OK\r\n”);

printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出信息。
printf()函数的调用格式为: printf("<格式化字符串>", <参量表>)。
通常意义上format的格式如下:%[flags][width][.prec][F|N|h|l]type,为方便观看或速查截图如下:
~~~~~
(, 下载次数: 391)
~~~~~
(, 下载次数: 399)
~~~~~
(, 下载次数: 361)
~~~~~
(, 下载次数: 393)
~~~~~
(, 下载次数: 394)
~~~~~

(, 下载次数: 420)


4.sprintf-----开发指南中原句有sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);//将LCD ID打印到lcd_id数组
在将各种类型的数据构造成字符串时,sprintf 的强大功能很少会让你失望。sprintf 跟printf 在用法上几乎一样,只是打印的目的地不同而已,前者打印到字符串中,后者则直接在命令行上输出。通俗的说,sprintf只是把双引号里面的东西格式化以后放到   以第一个指针参数所指向的地址为起始位置   的字符串中。更通俗的说就是对一个数组进行了赋值。

如需了解更多,比如重定向常用的两种方法以及各个知识点的详细讲解,可参考一下网址(也是本次参考网址):
【1】http://blog.csdn.net/bruce0532/article/details/4719540
【2】http://www.openedv.com/posts/list/11229.htm
【3】http://www.openedv.com/posts/list/44609.htm
【4】http://infocenter.arm.com/help/topic/com.arm.doc.dui0349bc/DUI0349BC_rvct_libraries_guide.pdf
【5】http://www.360doc.com/content/11/0707/08/4384349_132051931.shtml
【6】http://wenku.baidu.com/view/d68e44d233d4b14e85246803.html?re=view
【7】http://wenku.baidu.com/view/8a7e03ee8762caaedc33d45a.html
【8】http://wenku.baidu.com/view/69ef1a68bed5b9f3f80f1c58.html
【9】http://wenku.baidu.com/view/3b71260471fe910ef12df8a5.html
【10】http://baike.baidu.com/link?url=UtPj_ad7DpXvDhbfqnsORinaLfE9c3t9-kPxIkyrsOrGAv7whURDeCvxxLO-3xreGiRz-FT1eatvkEfqrMXq0a
【11】http://blog.csdn.net/bruce0532/article/details/4716709


------------------------------------隔一下--------------------------------------
现在时间2015年07月24日 22:06:29,一会儿改一下楼主位的更新时间,定为每晚23:45前完成更新即可,不作其他时间约束,否则有时候会出现想更新的时候觉得时间早,玩会游戏,越到后面越不想写,有时候可能还会有其他事情影响,自己时间观念也不强,凡事能早十分钟别晚三十秒,就到这吧,有点小累。


作者: w417074951    时间: 2015-7-25 08:43
回复【29楼】龙之谷:
---------------------------------
cool    ..
作者: w417074951    时间: 2015-7-25 09:02
回复【28楼】龙之谷:
---------------------------------
看楼主的帐号的等级和回复数,应该实在不能说是菜鸟了把,太自谦了把,现在我想说一下我的个人看法,楼主这样坚持不懈大家都是鼓励和敬佩的,但是个人认为或者我开始学的时候也是请教过原子哥,怎么学STM32最快,原子哥的答复是找个题目,做项目,边做边学,哪不会学哪,项目做完,涉及到的东西就都差不多会了,有的可能不是特别透彻,但是也基本可以了。
不是说否定楼主的一个实验一个实验的做下去不好,不是的,这是最好最全面的路子,是很好的,但可能时间要久一点,比如说我原来也是学的原子哥的mini板子,后来画板子,做项目什么的,到现在为止也不会用DMA,因为没有遇到用的需求,但是我现在有信心遇到了,学一下,研究研究就差不多可以做了,最多多花点时间呗,比如我学会定时器的第一个项目是做智能车,定时采集赛道,学PWM是控制电机,AD,IIC,单总线这些都是接传感器学会的,SPI是接个RFID学会的等等,哦还有,AD我写了很多次,包括32,51,zigbee什么的,但是到现在为止真没有一次用过DA,说真的我现在也不会,但是现在要真的用,也未必就好久才能学会把。
实验都是原子哥精心编排的,我只要画板子,用32,就用原子哥开发板上用的CPU,为什么?编程序方便呀,原子哥的例子就是最好的。但是很多时候是需要变通的,不是稍微改改就好,我还记得我以前PWM那次用的是TIM1,是mini上我记得是高级定时器,原子哥的例子是TIM3把,配置不是很一样,我就卡了很长时间,最后才找到就是一个语句,或许你写的时候,你也会重新翻书学的。
我也不知道我说清楚我意思没有,我是看楼主是个热心帮别人的人,所以说了下我的经历,也不值得什么借鉴,总之我还是支持你,是最支持的,我写的长,对把?哈哈,一起加油。
作者: wn1900    时间: 2015-7-25 09:40
回复【31楼】w417074951:
---------------------------------
赞同
作者: ch_1964    时间: 2015-7-25 10:33
楼主,不觉得库函数延时有问题吗?还是我哪里弄错了,请教
作者: 正点原子    时间: 2015-7-25 11:07
回复【29楼】龙之谷:
---------------------------------
不错,第三篇了。。。
作者: 龙之谷    时间: 2015-7-25 18:20
回复【31楼】w417074951:
---------------------------------
Thanks for sharing...

鉴于你是写的最长的,我由衷表示感谢,并计划写一个比较长的回复,哈哈

首先关于学习方法你说得很清楚也很有道理,我现在一步一步学习的一个主要原因是个人性格决定的吧,总感觉如果不走一遍感觉陌生不踏实,对掌握这款单片机的程度没有信心,一步步走完后心里有底,同时这样也是积累,以后有相关工作也能用到这些材料。另一方面,自己开发的一个小东西功能差不多了公司也不着急出成品,正好借着这段时间打打基础。看你的开发态度,阔达自信,希望完成实验后我能达到你的层面,赞一个。

关于菜鸟这个词,我感觉自己对STM32单片机的不了解是全方面的,提到一个点,理解都是含糊摩棱两可,也是认识到与老鸟、大神的巨大差距而写着玩的。

再次感谢你的支持,共同进步
作者: 龙之谷    时间: 2015-7-25 18:20
回复【32楼】wn1900:
---------------------------------
赞同
作者: 龙之谷    时间: 2015-7-25 18:23
回复【33楼】ch_1964:
---------------------------------
不觉得,因为我没用过库函数

这个建议你还是找自己这方面原因,原子哥程序多少人在用,经得起考验

尽信书不如无书,但在自己初级阶段还是要相信大家公认的经典
作者: 龙之谷    时间: 2015-7-25 18:25
回复【34楼】正点原子:
---------------------------------
哈哈,离完成就剩下八十几天了
作者: w417074951    时间: 2015-7-25 19:04
回复【35楼】龙之谷:
---------------------------------
这么谦虚,你也太抬举我了,额,那我只有努力努力,一起努力。
作者: 非洲小男孩    时间: 2015-7-25 21:10
写的很好,龙兄!我认真看了一遍,学习了知识。放假了,别人回家了。我在学校准备国赛,随便再系统学学32,论坛里大神很多,都是学习的榜样,每晚再跟你学学
作者: 龙之谷    时间: 2015-7-25 22:30
第〇四天:2015年07月25日  周六     例程:串口通信实验

感受:感觉今天写的东西有点傻,高手低手感觉无趣的尽快绕行,仅当写给自己备查的吧。

1.经常心里不踏实,每次需要配置某一功能时,都要拿起开发指南再对照参考手册一句一句更改,配置完成以后离开书本感觉空空的。今天分析一下原子哥串口配置,分解一下配置流程,先来个图 (, 下载次数: 411)
这是串口1的配置过程,细分的话有0~5一共六部分,之所以名为0部分是因为它仅仅是一个运算过程,单纯为第二部分使用作了相应运算。
第一部分:使能时钟、配置端口,这个不用说了,使用到端口都会进行的操作,基础操作。
第二部分:串口通信波特率很重要,通过参考手册波特率配置寄存器BRR的配置公式(第0部分进行了计算)进行配置即可,基础操作。
第三部分:配置控制寄存器,这个寄存器很重要,配置它提供了正常通信的基础,需要认真置位相关位,有些难度。
第四部分:配置优先级,一般涉及到中断都会配置优先级,使彼此按照重要程度排序,基础操作。
第五部分:使能,全部配置完成以后才能也必须使能,使其进入工作状态,基础操作。

这二十多行的代码本来感觉有一定难度,细分以后,除了需要对少寄存器研究注意一下认真配置赋值以外大部分都是基础性操作。

综上,配置某项功能的一般过程:使能时钟、配置端口-----查找相关寄存器,并按照需要配置。按照这简单暴力的思维模式进行外加开发指南等书籍辅助,寄存器配置没有想象中的那么难了。

2.XXX_IRQHandler与XXX_IRQn-----针对STM32F407等系列
前者XXX_IRQHandler:中断向量入口,中断函数名,定义于startup_stm32f40_41xxx.s
后者XXX_IRQn:中断号,中断时会产生中断请求信号,该信号告诉CPU是哪个中断请求,这个信号就叫做中断号,定义于stm32f4xx.h

3.对于开发指南里面定义的接收协议,如果初学看不懂建议多看几遍,不要轻易网络发问,网络上不大可能讲的比书上更详细到位,每看一遍都会慢慢理解,并逐渐感受到其精妙之处。同时,这个接收协议不是你以后开发必须的,甚至以后开发不会用到,但协议的思路是非常精妙的,值得深入研究。

------------------------------------隔一下--------------------------------------
现在时间:2015年07月25日 20:24:20,刚下班有点热,不想吃饭,现在有点饿,更到一半进退两难,买噶。先吃饭去,饿了没动力。
2015年07月25日 21:24:26,吃完饭了,这周是个小周末,按公司规定,每个月最后一周六天班,快下班的时候,老工程师说咱俩明天加班,...,老工程师人倒是挺好,不懂得地方耐心指导,只是自己底子薄,问不出高深的问题。
本来感觉有点累,想着怎么写省点事,但看到回复鼓励,静下心来按计划写吧,继续...
------------------------------------隔一下--------------------------------------

今日整理:(比较基础,自己经常混淆点,高手绕行)
1.RAM、ROM、FLASH、EEPROM
-----RAM(Ramdom Access Memory)随机存储记忆体,临时存储介质,可称为内存。可分为静态RAM(SRAM)和动态RAM(DRAM),SRAM速度非常快,是目前读写最快的存储设,DRAM则由于有较低单位容量价格,被大量采用作为主记忆。DRAM中比较知名的DDR RAM(Date-Rate RAM)也称作DDR SDRAM, 突出之处在于它可以在一个时钟读写两次数据, 这样就使得数据传输速度加倍了。
-----ROM(Read Only Memory)只读记忆体,用来存储和保存数据,掉电不丢失。缺点是不易更改。
-----FLASH MEMORY具有ROM掉电保存的优势,又可以在需要的时候任意更改,因此逐渐发展壮大。Flash主要有两种NOR Flash和NADN Flash。NOR Flash的读取和我们常见的SDRAM的读取是一样,用户可以直接运行装载在NOR FLASH里面的代码,这样可以减少SRAM的容量从而节约了成本。NAND Flash没有采取内存的随机读取技术,它的读取是以一次读取一块的形式来进行的,通常是一次读取512个字节,采用这种技术的Flash比较廉价。用户不能直接运行NAND Flash上的代码,因此好多使用NAND Flash的开发板除了使用NAND Flah以外,还作上了一块小的NOR Flash来运行启动代码。

由于FLSAH通信速度慢,所以上电后(部分)程序会被搬运到RAM中从其首地址开始运行。对于裸机(可能是电脑等非普通单片机)程序,如果代码量很小,代码并不是必须搬到RAM中,而是CPU根据它和ROM的通信协议,来ROM中按照(R15)地址顺序来逐个提取code来运行,但是很慢。所以一般会将向量表之类的需要快速响应的东西,放到ram中,其实ram够大,也可以将所有的代码放到RAM中。

2.idata, data, xdata, pdata-----主要涉及到51内核单片机,有些知识仍是学习其他单片机值得品味的

-----内部RAM的低128位,对应的C语言就是data
-----内部RAM的高128位,对应的C语言就是idata
-----外部RAM可以扩展到65536个,但是前面256个是一页,比较特殊,用pdata修饰,也可用xdata修饰
-----除了256这第一页的其他65280空间,自能用xdata来修饰

回过头来讨论pdata和xdata,这两个都能修饰外部Ram的第一页,但是,Pdata只能修饰第一页,即最前面的256个外部Ram,那么,这最前面的256个到底用Pdata还是Xdata好的呢?答案是Pdata,因为Xdata修饰的变量,用的是DPTR寻址,Pdata用的是R0和R1.DPTR因为是16位的,所以可以覆盖整个的64K外部Ram,R0和R1是8位,所以只能寻址最前面的256个,也就是外部Ram的第一页,但是,用R0寻址,比DPTR快一倍,代码也小的很多。

参考链接:(注:最后一个链接为  掉电瞬间将数据存入E2PROM的方法,未作引用,如有需要可借鉴其思路)
【1】http://blog.csdn.net/shenquanxi/article/details/6699563
【2】http://www.freescaleic.org/module/forum/thread-443287-1-1.html
【3】http://blog.csdn.net/zhang810413/article/details/2651106
【4】http://jingyan.baidu.com/article/1612d5004310ebe20e1eeed0.html
【5】http://zhidao.baidu.com/link?url=zNpGqBO1xNZbIbjvn09iAEc5gs-YEB2NkIrvzgbwEnaFHvtzRXK-GUhkaCUtZ6Ts2M7d8ZUHfozYa3AKuf85eK
【6】http://wenku.baidu.com/link?url=9jTSp0fO2DQrTYZKE0XIo945lIKhNfSwz6jGrsdZwnuBdr4m1Ccvdjl6x2BTUhGvYLLkY48v-8cF_mFgBLA2T9VYJ52I_kB1qYXTKG-dMBC


作者: 龙之谷    时间: 2015-7-25 22:37
回复【40楼】非洲小男孩:
---------------------------------
谢谢支持,上学的时候老羡慕你们这些参加比赛的了,加油,祝你国赛顺利
作者: mingjie2015    时间: 2015-7-26 11:27
希望能把每个工程上传一下
作者: 正点原子    时间: 2015-7-26 14:41
回复【41楼】龙之谷:
---------------------------------
不错,继续顶你
作者: 龙之谷    时间: 2015-7-26 16:15
回复【43楼】mingjie2015:
---------------------------------
上传工程没太大意义,有点画蛇添足的感觉,原子哥的例程很方便下载,也是经典,我的只是有一些稍微改动,如果后期改动稍大会上传对应.C/.H文件
作者: 龙之谷    时间: 2015-7-26 16:17
回复【44楼】正点原子:
---------------------------------
Thank you,YuanZiGe
作者: 龙之谷    时间: 2015-7-26 19:30
第〇五天  2015年07月26日  周日     例程:外部中断实验

题外话:现在时间2015年07月26日 17:50:41,加班回来就寻思赶紧写,九点以前必须完成,九点以后的极限挑战必须在线看直播啊,不能等,黄渤的幽默风趣、孙红雷的贪玩、黄磊的高智商、罗志祥的搞怪、王讯的实在,很久没追综艺了,跑男也追过,但从未这样迫切地想看一档节目,等不及啊等不及...

进入正题......


1.外部中断有一点需要大家注意,相信也会有很多人在此处产生过疑惑,直接上开发指南截图:
(, 下载次数: 389)
当进入多个中断共用服务函数时可以通过编写程序来判断识别到底是由哪个中断引起的。


2.抢占优先级、响应优先级-----中断优先级设置都会涉及
(, 下载次数: 393)
关于上图,第一,如果想知道抢占优先级和响应优先级什么意思请查看相关介绍书籍,有专门介绍;第二,如果是初学者不建议在此处浪费太多时间研究,知道如何使用即可,等掌握单片机到一定程度再回过头来弥补不足,效率会更高一些。那下面就是如何使用了
(, 下载次数: 397)
鉴于开发指南已经把NVIC封装起来,我们大可来个拿来主义,直接调用上图函数,上图的下半部分图表详细列出了不同中断分组下的抢占优先级、响应优先级的取值范围,调用此函数时不可超出其有效范围。一般情况下,建议中断分组设置为2,此时的抢占优先级和响应优先级取值范围都是0到3,设置时比较简单,也足够满足一般设计需求。


3.抢占优先级与响应优先级谁是霸道总裁?
(, 下载次数: 384)
而如果两个NVIC设置完全一样会有什么结果呢?据网络资料介绍,设置一样时会按照中断编号进行仲裁,同时产生中断则编号小的优先执行。





(, 下载次数: 409)


今日整理:KEIL编译常见问题整理
KIEL编译常见问题网上有一些人已经对常见问题进行了总结,在此进行整理(主要编辑了网文《吴鉴鹰总结的Keil编译常见问题》,其他或由于比较零散或由于无法下载没有整理,可通过下文相关链接查看),整理结果见附件,如遇到问题可优先检索一下,提高效率。


附件一:KEIL编译常见问题整理文档     附件二:常用函数的参数配置速查表

本文参考或相关链接:
【1】http://wenku.baidu.com/link?url=AbbDsAbu6sEAEq_iuL9LP4zHaSjC7aJpLYfbZe5jwBjfAv653aE6eh7IlOuOl0zNlwUqABfCAcJNQO15XkCVJt8xTRRPR22L7NdtyD3YGZm
【2】http://bbs.eetop.cn/thread-442371-1-1.html
【3】http://wenku.baidu.com/link?url=iXJZhuXBlTlg96xbNULSWXBPiJsNj0a4TGBTfYStVZJHKMnJZGiFaVaxcRjBpi8AoWfQmoi8Gwwm-Z9TjwhsS-bkbDL2o0OTW0GjWKO96Qy


PS:本来打算写几篇struct、enum等关键字的总结,既补充自己薄弱知识又比较容易组织材料,今天下午赫然发现站长Admin已经于一年前转发了一篇经典的总结,再看吧,自己肯定写不了那么好,倒打算参考借鉴后从基础层面去简单总结,满足一般需要。
刚开始总结,能力有限,不懂的地方非常多,但希望前期写一些基础的无需长篇大论分析的点,现在晚上写哪个知识点还需要白天上班思考寻找,最后还不一定满意,如果哪位坛友有相关点推荐,在此表示感谢,合适的话会尝试总结,谢谢!

作者: 正点原子    时间: 2015-7-26 19:52
回复【47楼】龙之谷:
---------------------------------
不错,又来了,哈哈。
作者: 龙之谷    时间: 2015-7-26 19:58
回复【48楼】正点原子:
---------------------------------
简直崩溃,越写越乱,写的也不是很满意,整体看起来简直不能忍,编辑了好几遍了,算了,吃饭缓解一下
作者: 正点原子    时间: 2015-7-26 20:51
回复【49楼】龙之谷:
---------------------------------
要耐心啊,呵呵
作者: 龙之谷    时间: 2015-7-26 21:41
回复【50楼】正点原子:
---------------------------------
回头看看,确实着急了,写的也有些杂了,明天再写的时候改进一下方式,嘿嘿
作者: cxran2wms    时间: 2015-7-27 10:54
哈哈哈,好多人鼓励你啊。
我就是按原子哥的一步步学下来的
作者: 龙之谷    时间: 2015-7-27 19:07
回复【52楼】cxran2wms:
---------------------------------
是啊,坛友都很正能量,嘿嘿
作者: 龙之谷    时间: 2015-7-27 22:00
第〇六天  2015年07月27日  周一     例程:看门狗实验

(, 下载次数: 51)

1.看门狗注意事项

(, 下载次数: 60)

2.看门狗溢出时间

(, 下载次数: 60)

其中,prep取值范围【0,7】,rlr为低12位有效重装载寄存器装载值,取值【1,4095】。


3.在开发指南中只使用到了一个指示灯来展示给我们不进行喂狗的复位现象,在此基础上我们可以把另外一个指示灯有效利用起来,如图添加到喂狗操作之后来直接提示我们进行了喂狗操作。
[mw_shl_code=c,true] while(1) { if(Key_Scan(0) != 0) { Wdg_Feed(); LED1 = !LED1; } delay_ms(10); }[/mw_shl_code]

4.分频:
将一单一频率信号的频率降低为原来的1/N,就叫N分频。如把33MHZ的信号2分频得到16.5MHZ的信号,3分频得到11MHZ的信号,10分频得到3.3MHZ的信号。
 倍频:将频率提高到原频率的N倍,就是N倍频,原先并没有倍频概念,CPU的主频和系统总线的速度是一样的,但CPU的速度越来越快,倍频技术也就应运而生。它可使系统总线工作在相对较低的频率上,而CPU速度可以通过倍频来无限提升。那么CPU主频的计算方式变为:主频 = 外频 x 倍频。也就是倍频是指CPU和系统总线之间相差的倍数,当外频不变时,提高倍频,CPU主频也就越高。


(, 下载次数: 56)

关于struct的那些事:

1.结构(struct)是由基本数据类型构成的、并用一个标识符来命名的各种变量的组合。结构中可以使用不同的数据类型。


2.结构定义

(, 下载次数: 49)

结构名是结构的标识符不是变量名,结构名不是必须的,省略它则成为无名结构(记忆中,但未找到确切资料佐证:如果定义多个无名结构是可以的,系统内部会进行区分,但此时定义结构变量时一定紧跟结构定义之后)。构成结构的每一个类型变量称为结构成员,它像数组元素一样,但数组中元素是以下标来访问的,结构则是按变量名来访问成员的。


3.结构变量定义

定义方式一:
(, 下载次数: 54)
上图定义了一个结构名为string的结构变量person,如果省略变量名person,则变成对结构的说明。
用已说明的结构名定义结构变量则为定义方式二。
定义方式二:
(, 下载次数: 59)

4.结构变量的使用

结构成员的表示方法为:结构变量.成员名
可以将“结构变量.成员名”看作一个整体,则这个整体的数据类型于结构中该成员的数据类型相同,就可像普通变量一样进行各种运算等,非常简单方便。
对结构变量的初始化可以统一初始化,也可分别初始化。如可令person.age = 20等。

5.结构简单的实际应用

第一,常见的是将一些相关度比较高的变量集中在一起,如日期可以定义为
struct date
{
   char second;
   char minute;
   char hour;
   char day;
   char month;
   int year;
}tm;
如果需要使用多个时间变量,这样的定义就方便许多,同时将其进行了模块化,维护也变得简单。
第二,在第一的基础上,个人感觉,当工程比较大的时候可以每个文件为它自身的全局变量定义一个结构体,比如串口实验中,可能会使用到接收数组、数组下标、接收完一组数据标志位,可定义为
struct uart2
{
   uchar Flag;
   uchar Num;
   uchar table[256];
}UART2;
这样的话即使变量多也比较容易区分与处理,此点也是重新熟悉学习struct的原因所在,打算在以后的工作中进行使用。


(, 下载次数: 44)

【1】http://baike.baidu.com/link?url=CVV6lDRXMqlX7oVw96CPBFjhM2DCkHTP6rEU2dzX7PIW9RwLHIsh_wcoLRiYTot1dquwwzB-vsWnOEFgsS4hH_
【2】http://baike.baidu.com/link?url=xMm3HT6IIcMpkC2ue5zsHC9cb_qIbyL-1HaoKCBj6c8E7rFSphJUEdB25NWxhZlbs-DmhQ5oa-K1KECcH0DeSq
【3】http://www.openedv.com/posts/list/33246.htm
【4】http://www.alex999.com/c_language_structure.html
【5】http://blog.sina.com.cn/s/blog_8c798c6c0100u1f0.html(结构体字节对齐--本文未介绍)
【6】《C语言程序设计》--谭浩强老师     (注:以后涉及到C语言的基本都会参考此书,故仅在此标明一次)

作者: persevere    时间: 2015-7-27 22:30
帅气,龙哥,每晚跟着你学
作者: 正点原子    时间: 2015-7-27 22:37
回复【54楼】龙之谷:
---------------------------------
顶,再来一篇给你置酷
作者: 龙之谷    时间: 2015-7-27 22:52
回复【55楼】persevere:
---------------------------------
谢谢支持,互相学习,哈哈
作者: 龙之谷    时间: 2015-7-27 23:03
回复【56楼】正点原子:
---------------------------------
稍等等,原子哥,本来我还想我写到什么时候你能给个酷,最坏情况是坚持到90天的时候你因为我的耐力给了酷,我真是要找个地缝了

你的这句话给我很大鼓励,酷对我而言我还不足以承受,不要给我太大压力,倒是想坚持完90天后能够得到个酷,哈哈

还有就是我每天在人少的时候尽量统一回帖,减少自己登上最新回帖的几率,就是感觉自己的这些还拿不出手

非常感谢原子哥鼓励
作者: 逍遥居士_888    时间: 2015-7-27 23:12
回复【31楼】w417074951:
---------------------------------
我的想法也是如此,但是对于我等菜鸟来说,得首先把教程都理解了,懂了一些,然后在做小项目。
我这两天学GPIO和外部中断。都深刻理解了。然后自己做一个外部中断和按键的项目,优先级啥的自己在确定要求时随意写的。每一步 每个外设的程序我都重新敲出来,不去想原子哥的教程,仅仅是想它是如何来的,成为自己的内容。敲出来  这样掌握才会充分。
作者: 正点原子    时间: 2015-7-27 23:21
回复【58楼】龙之谷:
---------------------------------
好的,那就如你所愿,你能坚持90天,我送个礼品给你。
作者: 龙之谷    时间: 2015-7-28 20:19
回复【60楼】正点原子:
---------------------------------
受益于原子哥再收原子哥的礼品真是有点不好意思,不过蛮期待的,哈哈......
作者: cxran2wms    时间: 2015-7-28 20:46
回复【60楼】正点原子:
---------------------------------
哈哈哈,原子哥太有情怀了。
作者: 正点原子    时间: 2015-7-28 22:27
回复【61楼】龙之谷:
---------------------------------
别客气,我奖励勤奋的学生。
作者: 正点原子    时间: 2015-7-28 22:27
回复【62楼】cxran2wms:
---------------------------------
呵呵
作者: 龙之谷    时间: 2015-7-28 23:19
第〇七天  2015年07月28日  周二     例程:再谈独立看门狗

一下班就开始整理,中间就吃了个饭,写到九点半的时候,把第一部分写完了,关闭其他窗口时错把浏览器窗口关掉了,整个人都不好了,简直震惊了……以后还是先用word写,崩溃了。所以大家看到的第一部分是我含着眼泪写完的!!!
(, 下载次数: 53)

1.
 独立看门狗分为硬件看门狗和软件看门狗两种。

2.
软件使能是通过软件设置寄存器位配置,软件使能的看门狗,只有在设置了相应的寄存器位后才能开始工作,一旦开始工作,只有系统复位才能让它停止工作。 我们通常使用的看门狗即通过配置寄存器使能的就是软件看门狗。那么我们是否可以纯软件使能与去除使能(软件)看门狗? 

[mw_shl_code=c,true] while(1) { k = Key_Scan(0); if(k == KEY1_PRESS) { IWDG->KR = 0XCCCC; //使能看门狗 } if(k == KEY0_PRESS) { Wdg_Feed(); LED1 = !LED1; } if(k == KEYUP_PRESS) //软件复位 { Sys_Soft_Reset(); } delay_ms(50); }[/mw_shl_code]



如上图,在原子哥例程基础上主要进行如下调整:1.将软件使能看门狗语句从看门狗初始化函数中剪切到if判断语句中;2.sys.h中软件复位函数复制到if判读语句中。结合按键操作我们可以得出:

第一,不使能看门狗但进行喂狗操作不会对程序运行产生影响,推至寄存器层面分析,我们对一个无关紧要不起作用的寄存器进行写操作除了浪费一点时间外确实不会产生其他影响。第二,注释掉第二条if判断,保持喂狗操作和指示灯翻转保持运行,此时按下按键使能看门狗,程序照常运行,我们再按下复位key_up按键,此时程序重启启动,看门狗则从使能状态转为去除使能的状态,我们实现了基于同一程序的软件控制(软件)看门狗使能与去除使能的功能。


3.STM32的独立看门狗可以是硬件使能或软件使能,硬件使能是通过设置选择字节配置,硬件使能的看门狗,在系统上电之后就开始工作,一旦开始工作就没有办法让它停止工作且必须通过擦除相应的选择字节位关闭硬件看门狗功能。

(, 下载次数: 23)
(, 下载次数: 49)


通过上图可以发现,硬件看门狗应该是写在了
flash中,整个过程我们通过烧写程序过程完成,而程序运行中并没有参与使能,所以复位后硬件看门狗状态不会变化。那么,我们是否可以通过软件来控制硬件看门狗的使能于去除使能呢?
在此,个人想法:我们可以类比于软件控制软件看门狗以及开发指南stmflash章节原理,在程序运行时通过改写相应选择字节来关闭硬件看门狗,至于是否能够在运行时改写相关字节而不影响单片机正常工作以及改写是否成功则有待验证。在此不作验证的原因:其一,网络关于硬件看门狗资料较少,其选择字节所在位置没有查到;其二,涉及到stmflash章节,虽有些许了解,没有进行实际多次测试,还待进一步掌握;其三,实际应用价值不大,甚至我们一般都用不到硬件看门狗;其四,今天实在没有时间了。(mark-----待验证)


(, 下载次数: 52)

狡兔三窟的enum

1.枚举:将变量的值一一列举出来,变量的值只限于列举出来的范围之内。之所以叫枚举,也可以说是可以把存在的情况或值一一列举出来。

2.枚举变量定义方式与结构变量定义方式基本一致。如
(, 下载次数: 50)

上图中的标识符就是枚举变量可以被赋予的整型常数,因为数据类型都是固定的整形常数,所以直接使用标识符而无需数据类型的修饰

可以在声明的时候对枚举变量的每一个元素进行整型常数赋值,而如果没有进行赋值操作,则系统自动从0开始递增进行赋值操作,期间,如果某一元素进行了赋值,则其后未被赋值元素会以它的值为基础依次递增自动赋值。
(, 下载次数: 50)
加入enum box BOX1;则我们可以通过BOX1 = pen;来给枚举变量进行赋值,但不可以对其进行直接赋算数值的错误操作如BOX1 = 4则是错误的,这时需要强制类型装换才可以,如BOX1 = (enum box)4,才是正确的。

3.枚举变量中的每一个枚举元素都是按常量处理,不可在程序中对它进行除声明外的其他赋值操作。


4.枚举变量的应用比较明显的体现就是星期数,星期几有从周一到周日的七种情况,但具体到某一天是周几则是确定的,不可能某一天既是周一又是周二,也就是说枚举变量具有唯一指定性。


5.枚举的简单实际应用

我们可以把某一只具有少数整型取值值的变量定义为枚举变量,如状态标志位flag,只有两种状态,可以定义为
enum BOOLE
{
    err = 0;
    true = 1;
}
flag;
这样的处理便于程序的管理与维护,增强了可读性。

6.来个可能不是很形象的比喻:一个兔子窝有三个门,分别是M1、M2、M3,这是固定的,兔子从洞里出去需要穿过哪个door?这个door就可以定义为枚举变量,而M1、M2、M3则分别是它可取值的
元素。

7.结构只是对不同变量进行了统一管理,结构中元素之间没有直接的关系,只是我们逻辑上认为比较靠近的变量的统一管理,每个变量可以是任何数据类型,可以参加运算
;而枚举则是枚举变量对枚举元素的唯一性选择,枚举元素之间是彼此互斥的整型变量。

(, 下载次数: 48)


【1】http://www.openedv.com/posts/list/5033.htm
【2】http://bbs.21ic.com/icview-163512-1-1.html
【3】http://www.21ic.com/jichuzhishi/2012-10-12/146626.html
【4】http://wenda.haosou.com/q/1369032011064427?src=150
【5】http://blog.csdn.net/logogcn/article/details/7879398

作者: 龙之谷    时间: 2015-7-28 23:25
回复【63楼】正点原子:
---------------------------------
偶上班快三年了,从事相关工作倒是不到一年...

把你当成老师,自己确实还是个成绩不太好的学生...
作者: 正点原子    时间: 2015-7-28 23:27
回复【65楼】龙之谷:
---------------------------------
顶你。。。。
作者: 龙之谷    时间: 2015-7-28 23:39
鉴于今天发生的写好部分被自己误操作丢失,开启一下吐槽模式

科目二刚报上名,8月19日考试,还有差不多三周时间,20个课时,周六周日每天刷四个课时的节奏。这两周老工程师又给安排了开发小东西的任务,急着做出来,昨天工程师指导了原理图,今天初步布局了PCB,明天尽量把PCB线连接个大部分,争取后天发送制板,然后留一周时间左右编程,希望一切顺利吧。

每天更新一篇小短文,用时远超预期,今天由于重写第一部分总共用了估计五个小时,我勒个去,这也让自己渐渐认识到写书的难度有多大,写出经典的书籍难度更是不必说,在此,向每一位真心写书的作者致敬!
作者: 正点原子    时间: 2015-7-29 00:09
回复【68楼】龙之谷:
---------------------------------
可以先在word里面编辑好,然后黏贴过来,比较不容易出问题。
作者: 葫芦兄弟    时间: 2015-7-29 18:03
等楼主更新 顶!
作者: ch_1964    时间: 2015-7-29 20:04
太强了,好会举一反三
作者: 龙之谷    时间: 2015-7-29 23:30
第〇八天  2015年07月29日  周三     例程:窗口看门狗
(, 下载次数: 54)

1.关于窗口看门狗在开发指南V1.1版本148页中的窗口计数器T【6:0】共七位参与窗口看门狗超时工作,此页所提到的T【5:0】应该是书写错误,我记得好像论坛里坛友已经对此进行了指正,请注意。

2.通俗的说,窗口看门狗就是一个既不能早喂也不能晚喂的狗,喂的早就会把狗“撑死”,单片机复位,喂的晚就会把狗“饿死”,单片机同样复位,这两种情况就是对应的上下窗口。而上一个例程的独立看门狗最大的区别在于独立看门狗不能喂的晚,但可以在它饿死前任何时刻喂狗,哪怕你从打开看门狗开始就不停喂狗。从这个意义上说,窗口看门狗具有更加严格的监视功能。


3.超时计算公式

(, 下载次数: 50)

4.超时时间表
(, 下载次数: 53)

最小超时就是喂狗不得低于的时间,在此时间内喂狗,则喂狗过早,窗口看门狗会“撑死”;最大超时则是和独立看门狗道理一样,如果超过这个时间喂狗,看门狗已经“饿死”。

5.窗口看门狗带有提前唤醒中断,开启后,在窗口看门狗要“饿死”前的瞬间会进入中断,在中断处理事项。在中断处理中是否喂窗口看门狗大家持不同看法:一种如开发指南中的在窗口看门狗中断中进行喂狗;第二种则是不可在窗口看门狗中断中进行喂狗,只能在此写下复位前的“遗嘱”,如保存重要数据等(见相关链接)。

6.我感觉第二种做法应该是更加充分的利用了窗口看门狗的特性,窗口看门狗比独立看门狗严格之处在于程序人员需对窗口看门狗两次喂狗动作间的程序运行时间把握的很准确,一旦程序跑到其他非预期处很有可能窗口看门狗会“饿死”或“撑死”,而一般程序中满山遍野的独立看门狗喂狗操作则不容易检查到这种跑飞情况。如果把窗口看门狗的喂狗操作放入中断中,它的这个特点则不会充分体现出来。

7.今天在实验主要是基于不在中断中喂狗这个前提下进行的简单实验,也是参考了坛友的程序,主函数处理如下
[mw_shl_code=c,true] wr = WWDG->CFR & 0X7F; //window value tr = WWDG->CR & 0X7F; //counter value if(tr < wr && flag == 0) { Wwdg_Feed(WWDG_CNT); printf("正在喂狗!\r\n"); } if(Key_Scan(0) == KEY0_PRESS) { flag = 1; //是否喂狗标志位,置位后停止喂狗操作 }[/mw_shl_code]

如上图,一旦达到喂狗条件便开始喂狗,保持程序正常运行,flag是一个标志位,一旦按键key0按下则置位flag停止喂狗,窗口看门狗即将超时的时候会进入唤醒中断,我们在中断中进行如下处理(写下“遗嘱”),等待系统复位。
[mw_shl_code=c,true] WWDG->SR = 0X00; //clear flag LED1 = !LED1; printf("进入中断\r\n");[/mw_shl_code]
(, 下载次数: 61)

共用体union
1.定义:使几个不同的变量共同占用同一段内存的结构成为共用体。

2.共用体变量与结构体变量定义方式类似,共用体与结构的区别在于共用体所占内存长度为最长成员的长度,而结构则是大于(字节补充对齐引起)等于各成员所占内存的总和。

3.共用体特点:其一,同一内存段可以用来存放几种不同类型的成员,但在每一瞬时能且只能存放一个成员,即只有其中某一个成员是有效;其二,共用体变量中起作用的是最后一次放进去的成员,在存入一个新的成员数据后,其他成员都失去作用;其三,共用体变量的地址和它各个成员的地址是同一地址;其三,不能在定义共用体变量时对它初始化。

4.假如定义,
union data
{
    uchar i;
   uchar j;
    uint   k;
}a;
则可以在程序中赋值a.i = 5;此时可以引用共用体变量中的i成员,当然此时的j成员如果使用的话也是等于5,因为他们的地址是一致的。

5.共用体可以把几个同一时刻彼此互斥、不会同时被使用的变量放在同一起始地址的区域中,使用得当,共用体可以有效节省空间,提高程序的紧凑性。简单使用实例
假设有若干人员的数据,其中有学生和教师。学生数据包括:姓名、号码、性别、职业、班级。
                                                               教师数据包括:姓名、号码、性别、职业、职务。
可以看出,学生和教师所包含的数据只有最后一项是不同的,可以统一进行管理:
struct data{
    int num;
   char name[10];
    char sex;
    char job;
    union{
        int banji;
        char position[10];
    }category;
}person[2];     //先假设人数为2人
从上定义可以看出,班级或职务两个变量在不同job的情况下只有一个变量有效的,班级和职务是不会同时出现的,由每个人员job来确定确定需要处理的是班级还是职务信息。当然,我们可以不使用共用体,把两个变量同时定义,不适用的变量赋值为0,但显然使用共用体节省了空间,并且更符合人们平常的表格思想。
(, 下载次数: 53)


(, 下载次数: 35)


【1】http://www.openedv.com/posts/list/13292.htm
【2】http://blog.csdn.net/jiangnanyouzi/article/details/3158702
【3】http://c.biancheng.net/cpp/html/450.html
【4】http://www.openedv.com/posts/list/0/56555.htm#322181
【5】http://www.openedv.com/posts/list/0/6274.htm#322182

作者: 龙之谷    时间: 2015-7-29 23:30
回复【69楼】正点原子:
---------------------------------
吃一堑长一颗痣,哈哈
作者: 龙之谷    时间: 2015-7-29 23:31
回复【70楼】葫芦兄弟:
---------------------------------
回复【71楼】ch_1964:
---------------------------------
谢谢支持,共同进步...
作者: 正点原子    时间: 2015-7-30 00:59
回复【72楼】龙之谷:
---------------------------------
顶。。。。
作者: machao070    时间: 2015-7-30 08:00
marking……
作者: 正点原子    时间: 2015-7-30 14:09
坚持超过一周了,楼主不容易啊。
作者: 正点原子    时间: 2015-7-30 20:32
坐等楼主今晚更新。。。。
作者: 非洲小男孩    时间: 2015-7-30 23:07
回复【78楼】正点原子:
---------------------------------
哈哈,彼此彼此。每天向楼主学习已经成为一种习惯,好有正能量。其实我更想了解的是关于工作的一些情况,毕竟我身处学校,膜拜外面搞技术的大神。
作者: 正点原子    时间: 2015-7-30 23:31
回复【79楼】非洲小男孩:
---------------------------------
楼主今天还没更新,是不是有什么变故啊,呵呵。
作者: 龙之谷    时间: 2015-7-30 23:49

第〇九天  2015年07月30日  周四     例程:定时器中断实验

(, 下载次数: 51)


1.定时计数器分类:STM32F4定时器有TIME1和TIME8等高级定时器,也有TIME2~TIME5、TIME9~TIME14等通用定时器,还有TIME6和TIME7等基本定时器,总共有14个之多。

2.三种定时器区别
(, 下载次数: 56)

3.频率:物质在1s内周期变化的次数叫做频率。常用f表示,单位为Hz,与周期成倒数关系,即1Hz=1/s。为加深记忆,按部就班计算,1KHz即为1s变化1000次,即1ms变化1次1KHz = 1/ms,同理1MHz = 1/us。

4.溢出Tout时间计算公式:     Tout = ((arr+1)*(psc+1))/Tclk;
其中,arr为自动重装值;
          psc为时钟预分频数;
          Tclk为输入时钟频率,本例程TIME3为84Mhz。

根据例程,当psc为(8400-1)时,即进行8400分频,此时技术频率为84MHz/8400 = 10KHz,也就是1s计数10K次,每次计数需耗时1/10000(s)。计数arr次需耗时arr*(1/10000)(s),等效于arr*(1/10)(ms),所以,当arr为(5000-1)时,每次溢出需5000*(1/10)(ms),即500ms。

5.例程中,将两个指示灯分别用于主函数和中断中闪烁,可以在此基础上,通过定义一个全局标志变量flag来使两个指示灯几乎同步,观察延时函数和定时计数器两者是否吻合。
定义一个全局变量flag以后,进行如下调整:其一,在中断函数中添加flag

void TIM3_IRQHandler(void)

{

        if(TIM3->SR & 0X0001)

        {

               LED1 = !LED1;

               flag = 1;     //一旦进入中断则置位同步标志位

        }

        TIM3->SR &= ~(1 << 0);

}

其二,将主函数进行一些调整

        while(1)

        {

               while(flag == 0)     //等待同步标志位置位

               {

                   delay_us(2);

               }

               LED0 = !LED0;

               delay_ms(500);

        }

此时主函数小灯闪烁频率为1s,定时计数器溢出时间为500ms,定时计数器一旦中断则置位标志位,两个小灯几乎同步开始闪烁,两者误差不超过2us,实际测试可以观察到两个小灯同步进行闪烁。此时我们将主函数中delay_ms(500)改为delay_ms(400),则可以观察到LED0每闪烁5次的同时LED1恰好闪烁4次,与预期一致,说明定时计数器与延时函数两者之间是协调的,如果有秒表等设备进行监测,应该会发现它们都是准确的。

(, 下载次数: 52)



位段
1.信息的存取一般以字节为单位。实际上,有时存储一个信息不必用一个或多个字节,如真、假二值判断。在计算机用于过程控制、参数检测或数据通信领域时,控制信息只占一个字节中的一个或几个二进制位,常常可以在一个字节中放几个信息。

2.位段:C语言允许在一个结构中以位为单位来指定成员所占内存长度,这种以位为单位的成员成为位段或位域(bit field)。利用位段能够用较少位数存储数据。

3.位段变量与结构变量定义类似。位段示意图
(, 下载次数: 57)

4.注意事项
其一,位段成员类型必须指定为unsigned或int类型;
其二,若某一位段要从另一个字开始存放,可用以下形式定义
unsigned   a:1;
unsigned b:2;//一个存储单元       
unsigned:0;
unsigned c:3;//另一存储单元 
     a、b、c应连续存放在一个存储单元中,由于用了长度为0的位段,其作用是使下一个位段从下一个存储单元开始存放。因此,只将a、b存储在一个存储单元中,c另存在下一个单元(“存储单元”可能是一个字节,也可能是2个字节,视不同的编译系统而异)。  
其三, 一个位段必须存储在同一个存储单元中,不能跨两个单元,如果第一个单元空间不能容纳下一个位段,则该空间不用,而从下一个单元起存放该位段。
其四,位段的长度不能大于存储单元的长度,也不能定义位段数组。
其五,位段可以在数值表达式中引用,它会被系统自动地转换成整型数。

5.同结构一样,我们可以把工程中仅需要几位来表示且功能性质比较相似的变量统一放在一块,节省空间的同时也便于管理。例如,程序中可能需要很多标志位,我们把这些标志位统一放在一个位段中,根据需要可以不断添加和去除,使其整体统一,框架清晰明了。


作者: 龙之谷    时间: 2015-7-30 23:51
回复【78楼】正点原子:
---------------------------------
今晚回来巨困,稍睡了会,整理的时间晚了一个多小时,汗

今天发帖真够惊险的,点击发送,感觉网页有点卡住,赶紧复制粘贴到WORD,果然网速不给力发送失败,真险,哈哈
作者: 龙之谷    时间: 2015-7-30 23:52
回复【79楼】非洲小男孩:
---------------------------------
回复【80楼】正点原子:
---------------------------------
已更新,请看官查阅,哈哈
作者: persevere    时间: 2015-7-31 07:57
顶下,让更多的人能看到
作者: w417074951    时间: 2015-7-31 09:35
楼主加油,赞赞赞
作者: 正点原子    时间: 2015-7-31 11:07
回复【82楼】龙之谷:
---------------------------------
贵在坚持,呵呵。
搭上末班车了。
作者: 西点    时间: 2015-7-31 11:09
用什么编译器写的程序了、?
作者: 龙之谷    时间: 2015-7-31 12:18
回复【87楼】西点:
---------------------------------
原子哥光盘中的MDK5
作者: 西点    时间: 2015-7-31 20:07
回复【88楼】龙之谷:
---------------------------------一直用3/4,没有用5.。。。。
作者: tuzihog    时间: 2015-7-31 22:03
时间还早
楼主好好加油
作者: 龙之谷    时间: 2015-7-31 23:04
2015年07月31日     今日更新前说明

今天进行了PWM实验,将整理部分简单概念性知识点,如有某位坛友不惜浪费时间在等楼主更新,今天可以做一些其他有意思的事情......

对于PWM实验,由于个人对此比较陌生,有一点抵触心理,相关材料也较多,一时整理不过来,另外明天还要加班,这几天也有点累了,等等等等不是理由的理由,就稍微整理了一点,给自己放个假......

祝好运!

作者: 正点原子    时间: 2015-7-31 23:10
回复【91楼】龙之谷:
---------------------------------
等你的更新啊。
作者: 龙之谷    时间: 2015-7-31 23:32
回复【84楼】persevere:
---------------------------------
回复【85楼】w417074951:
---------------------------------
回复【90楼】tuzihog:
---------------------------------
谢谢支持,共同进步
作者: 龙之谷    时间: 2015-7-31 23:34
第一〇天  2015年07月31日  周五     例程:PWM实验(一)

1.脉冲宽度调制(PWM),Pulse Width Modulation,简称脉宽调制,是利用处理器地数字输出来对模拟电路进行控制的一种非常有效的技术。
2.预装载寄存器和影子寄存器关系:预装载寄存器是我们可以写入或读出的寄存器,而影子寄存器是我们看不见、无法真正对其读写操作的,但确实使用中真正起作用的寄存器。预装载寄存器的内容可以随时传送到影子寄存器,两者是连通的,或者在每一次更新事件时才把预装载寄存器的内容传送到影子寄存器。
设计预装载寄存器和影子寄存器的好处是所有真正需要起作用的寄存器(影子寄存器)可以在同一个时间(发声更新事件时)被更新为所对应地预装载寄存器的内容,这样可以保证多个通道的操作能够准确地同步。如果没有影子寄存器,软件更新预装载寄存器时,则同时更新了真正操作的寄存器,因为软件不可能在一个相同的时刻同时更新多个寄存器,结果造成多个通道地时序不能同步,如果再加上例如中断等其他因素,多个通道地时序关系有可能会混乱,造成不可预知的结果。

相关链接:http://blog.sina.com.cn/s/blog_ad187b9601014to7.html




作者: 龙之谷    时间: 2015-7-31 23:37
回复【92楼】正点原子:
---------------------------------
今天只是更新了一丢丢,相关知识点太多了,自己对PWM也比较生疏,算是偷懒了

今天正好第十天,以后每十天偷懒一天,哈哈......
作者: 正点原子    时间: 2015-8-1 11:29
回复【95楼】龙之谷:
---------------------------------
不能偷懒啊,呵呵
作者: 非洲小男孩    时间: 2015-8-1 13:23
回复【95楼】龙之谷:
---------------------------------
     可以理解。白天上班,晚上回去还想休息一下,真正深入研究32的时间不多,加上总结又会花掉一部分时间,这已经到了11点半。我的建议其实也不一定每天都得更新,主要还是总结一些精华的东西,深入研究。仅供参考,哈哈。
作者: 龙之谷    时间: 2015-8-1 20:08
回复【96楼】正点原子:
---------------------------------
面壁......
作者: 龙之谷    时间: 2015-8-1 20:19
回复【97楼】非洲小男孩:
---------------------------------
非常感谢你的建议

之所以每天都更,主要是克服一下我个人的惰性,另外就是自己选的路,跪着也要走玩,开帖标题搁那了,当初标题“意气”用事了,哈哈

以自己现在水平,现阶段还玩不出比较上档次地实验,所以只能先打打基础,帖子里很多都是非常基础的点,恰恰也是自己会犹豫的点,所以就整理出来了

C语言的很多一些生疏地知识点如结构、联合等,基本整理出来了,以后这部分就不会每天准备了,整理工作减轻了一些,把更多精力放在实验上
作者: 坏男孩    时间: 2015-8-1 21:09
楼主好牛逼,顶你,我也以你作为榜样学习




欢迎光临 OpenEdv-开源电子网 (http://www.openedv.com/) Powered by Discuz! X3.4