• 关于开发中如何防止死等程序导致其它任务运行不了方法

     在嵌入式软件开发中,比如单片机的程序,我们一定会写到一个大的死循环的程序,也就是轮询IO口,通常用 while(1) { } 来实现大循环,程序就会在while(1)中不断的循环执行一些任务,但是,任务与任务之间如果存在延时,就会大大的削弱整个架构的实时性,虽然现在的高级单片机ARM已经具有了多线程的机制,但是避免不了的依然是要写死循环,也就是说,表面上看到程序是一起在跑的,其实是把时间切成若干份,然后进行调度,在linux内核中,fork一条进程需要调度,do_thread也需要进行调度。 最近在工作上遇到一个这样的问题,串口协议要求比如等到IO口为低电平,数据才能发送。关于这个问题,没别的方法,按照那个架构来说只能死等while(等到IO口低电平输出),但是这样就会遇到一个问题,如果一直死等,万一IO没有低电平输出,那么就会发生丢包的可能以及其他任务会被直接影响到运行,毕竟单片机一般采用的架构都是顺序执行的,但是看到有工程师做这样的处理,我也就学过来了,让while做超时处理,一旦在一定的时间内等待不到低电平输出,那么就让这个循环退出,这样就不会影响到其它任务的执行了,也降低了丢包了,但还是会有丢包,只能慢慢调试了,要是有高手看到麻烦教我一下,最近我们公司也是因为这个问题卡了很久,表示伤不起,我们来看一下是怎么实现的。

    时间:2018-04-27 关键词: 单片机 嵌入式 循环程序

  • 单片机PWM调制技术

     我们可以看看下图,下图就是一个典型的PWM的波形图。 T是一个周期,T1就是高电平所占用的时间,T2就是低电平所占用的时间。 如上图所示T1为脉冲宽度(就是导通时间),周期为T,则输出电压的平均值为U=VCC*T1/T=a*VCC,a是占空比,变化范围为0≤a≤1。VCC为电源电压,一般情况下使用单片机的VCC为5V。在电压不变的情况下,改变a的大小就可以改变输出电压的平均值。这就是单片机的PWM调制技术。 如何改变a呢?可以采用定时器,也可以用普通的延时,但是笔者推荐用定时器产生PWM输出信号,误差极小。

    时间:2018-04-27 关键词: pwm 单片机

  • 收藏!如何区别上升沿、下降沿、低电平、高电平

      如图所示: 数字电路中,把电压的高低用逻辑电平来表示。逻辑电平包括高电平和低电平这两种。不同的元器件形成的数字电路,电压对应的逻辑电平也不同。在TTL门电路中,把大于3.5伏的电压规定为逻辑高电平,用数字1表示;把电压小于0.3伏的电压规定为逻辑低电平,用数字0表示。数字电平从低电平(数字“0”)变为高电平(数字“1”)的那一瞬间(时刻)叫作上升沿。 数字电路中,把电压的高低用逻辑电平来表示。逻辑电平包括高电平和低电平这两种。不同的元器件形成的数字电路,电压对应的逻辑电平也不同。在TTL门电路中,把大于3.5伏的电压规定为逻辑高电平,用数字1表示;把电压小于0.3伏的电压规定为逻辑低电平,用数字0表示。数字电路中,数字电平从高电平(数字“1”)变为低电平(数字“0”)的那一瞬间叫作下降沿。

    时间:2018-04-27 关键词: 高电平 上升沿 单片机

  • 教你如何来看单片机外设A/D转换器ADC0804时序图

     如图,为单片机AD转换器的一种: ADC0804单片集成A/D转换器。它采用CMOS工艺20引脚集成芯片,分辩率为8位,转换时间为100µs,输入电压范围为0~5V。芯片内具有三态输出数据锁存器,可直接接在数据总线上。   各引脚名称及作用如下: VIN(+),VIN(-)——两模拟信号输入端,用以接收单极性、双极性和差模输入信号。 DB7~DB0——具有三态特性数字信号输出口。 AGND——模拟信号地。 DGND——数字信号地。 CLK——时钟信号输入端。 CLKR——内部时钟发生器的外接电阻端,与CLK端配合可由芯片自身产生时钟脉冲,其频率为1/(1.1RC)。 CS#---片选信号输入端,低电平有效,一旦CS#有效,表明A/D转换器被选中,可启动工作。 WR#---写信号输入,低电平启动A/D转换。 RD#---读信号输入,低电平输出端有效。 INTR#---A/D转换结束信号,低电平有效表示本次转换已完成。 VREF/2---参考电平输入,决定量化单位。 VCC---芯片电源5V输入。 打开ADC0804的数据手册,我们可以看到以下典型的电路接法: 我们可以用仿真软件画出来: 接下来,我们分析一下上图的工作原理: ①ADC0804的片选端CS连接U2锁存哭的Q7输出端,我们可通过控制锁存器来控制CS,这样接的原因是TX-1C实验板扩展的外围太多,没有多余的I/O口独立控制ADC0804的CS端,所以选择U2。 ② VIN(+)接电位器的中间滑动端,VIN(-)接地,因为这两端可以输入差分电压,即它可测量VIN(+)与VIN(-)之间的电压,当VIN(-)接地时,VIN(+)端的电压即为ADC0804的模拟输入电压。VIN(+)与电位器之间串联一个10kΩ电阻,目的是限制流入VIN(+)端的电流,防止电流过大而烧坏A/D芯片,当用短路帽短接插针ADIN后,电位器的中间滑动端便通过电阻R12与VIN(+)连接,此时调节电位器的旋钮,其中间滑动端的电压便在0~VCC变化,进而ADC0804的数字输出端也在0x00~0xFF变化。 ③ CLKR,CLR,GND之间用电阻和电容组成RC振荡电路,用来给ADC0804提供工作所需的脉冲,其脉冲的频率为1/(1.1RC),按芯片手册上说明,R取10kΩ,C取150pF,TX-1C实验板上为了减少元件种类和焊接方便,C选用的是104磁片电容。大家在设计自己的电路时,可选择150pF电容,否则会影响A/D的转换速率。 ④ VREF/2端用两个1kΩ的电阻分压得到VCC/2电压,即2.5V,将该电压作为A/D芯片工作时内部的参考电压。 ⑤WR#、 RD#分别接单片机的P3.6和P3.7引脚,数字输出端接单片机的P1口。 ⑥ 将AGND和DGND同时连接到实验板的GND上。我们在设计产品时,若用到A/D和D/A,一般这些芯片都提供独立的模拟地(AGND)和数字地(DGND)引脚,为了达到精度高,稳定性好的目的,最好将所有器件的模拟地和数字地分别连接,最后将模拟地与数字地仅在一点连接。 ⑦ INTR#引脚未连接,TX-1C实验板上读取A/D数据未用中断法,因此可不接该引脚。数字芯片在操作时首先要分析它的操作时序图,图4.4.6是ADC0804的启动转换时序图。 ADC0804转换时序图: 分析图4.4.6可知,CS先为低电平,WR#随后置低,经过至少tW(WR#)L时间后,WR#拉高,随后A/D转换器被启动,并且在经过(1~8个A/D时钟周期+内部TC)时间后,模/数完成转换,转换结果存入数据锁存器,同时INTR自动变为低电平,通知单片机本次转换已结束。关于几个时间的大小在芯片手册中都有说明。 我在写单片机程序启动A/D转换时就要遵循上面的时序,由于TX-1C实验板未用中断读取A/D数据,因此我们在启动A/D转换后,稍等一会儿时间,然后直接读取A/D的数字输出口即可。读取结束启动一次A/D转换,如此循环下去。力4.4.7是ADC0804读取数据时序图。 分析上图可知,CS先为低电平,WR#随后置低,经过至少tW(WR#)L时间后,WR#拉高,随后A/D转换器被启动,并且在经过(1~8个A/D时钟周期+内部TC)时间后,模/数完成转换,转换结果存入数据锁存器,同时INTR自动变为低电平,通知单片机本次转换已结束。关于几个时间的大小在芯片手册中都有说明。 我在写单片机程序启动A/D转换时就要遵循上面的时序,由于TX-1C实验板未用中断读取A/D数据,因此我们在启动A/D转换后,稍等一会儿时间,然后直接读取A/D的数字输出口即可。读取结束启动一次A/D转换,如此循环下去。力下图是ADC0804读取数据时序图。 分析上图可知,当INTR#变为低电平后,将CS#先置低,在RD#置低至少经过tACC时间后,数字输出口上的数据达到稳定状态,此时直接读取数字输出端口数据便可得的数字信号,读走数据后,马上将RD#拉高,然后再将CS#拉高,INTR#是自动变化的,当RD#置低tR1时间后,INTR#自动拉高,我们不必人为去干涉。 图4.4.6和图4.4.7是ADC0804启动转换和读取数据的时序图,这是启动一次和读取一次数据的时序图,当我们要连续转换并且连续读取数据时,有没有必要每次都把CS#置低再位高,因为CS#是片选信号,置低表示该芯片可被操作或处于能够正常工作状态,所以在写程序时,只要一开始将CS#置低,以后当要启动转换和读取数据时只需操作WR#和RD#即可。

    时间:2018-04-27 关键词: ad转换器 adc0804 单片机

  • 单片机编程开发技巧经验分享

     工作了7个月之久,对单片机的编程也开始慢慢熟悉起来,以前总是知道单片机就是定时器,状态机,中断这些东西结合起来效率是相当高的,但是自从接手开发GPF这个芯片之后,我发现了另外一种单片机的开发技巧,高手请绕道。 我们都知道,在程序中,延时会影响单片机的实时性能,导致效率明显降低,但是在GPF这个芯片的开发中,系统延时和初始化被供应商做到了一块,所以调用程序,必须要做一定的loop才能使得程序能够正常的跑起来,其实我也不知道她们为什么要这么做。 在工作中,改一份源码不是随随便便就可以改的,当时做了这么一个程序,源码我就不公开了,写个案例解释: void test() { int i = 0 ; int tick ; int BatteryStatus = 0; int Voltage ; int count = 0 ; int Voltage_value ; char ch ; scanf("%d",&BatteryStatus); while(1) { delay_20ms(); switch(BatteryStatus) { case 1: if(count == 50) { printf("0x%x\n",0xE1); count = 0 ; };break ; case 2: if(count == 50) { printf("0x%x\n",0x90); //发通用'1'信号 count = 0 ; };break ; default: break ; } count++ ; #if 0 ch = getch(); //假设我在这设立一个按键 if(ch == 'q') { printf("%x",0x48); break ; } #endif } } 在while循环中,首先进去是延时20个ms,然后count计数器加加,当加到50次也就是一秒钟了,然后清零。此时若按下按键,不会受到干扰,程序正常运行,效率依然很高。如果这时候delay_20ms改成delay_1000ms,程序扫描按键每次就要等待1s钟,影响效率。计数值可以自我估计一下,不需要太准,这样的程序在延时不需要太精准的可以实现和定时器差不多一样的功能。

    时间:2018-04-27 关键词: 编程 单片机开发 单片机

  • 嵌入式C实战项目开发技巧:如何对一个有规律的数组表进行位移操作

     就像下面的这个表 之前写过上面这个标题的一篇文章,讲的是以位移的方式去遍历表中的数据,效率非常高,但是,如果要实现一个乱序的流水灯或者跑马灯的话,思考一个这样的算法是不可取的,很费时间,也很费脑力,于是,今天就说一说查表法,如果在程序中运用查表法,不论多么复杂的程序,只要符合一张表,那都可以实现,非常简单,体力活而已,接下来看看下面这个程序,对上面这个进行操作吧。 [cpp] view plain copy#include #include //这里的行可以自由写,这样就不受限制,想做出什么样的效果都可以。 int array[][10] = { 0x03,0x00,0x00,0x00,0x00,//第一列 0x00,0x02,0x00,0x00,0x00, 0x0C,0x00,0x00,0x00,0x00,//第二列 0x00,0x04,0x00,0x00,0x00, 0x10,0x00,0x00,0x00,0x00,//第三列 0x00,0x08,0x00,0x00,0x00, 0x60,0x00,0x00,0x00,0x00,//第四列 0x00,0x10,0x00,0x00,0x00, 0x80,0x01,0x00,0x00,0x00,//第五列 0x00,0x20,0x00,0x00,0x00, 0xAA,0x55,0x00,0x00,0xC0,//end 0x00,0x00,0x00,0x00,0x00, }; void to_Q112_cmd_designator_LED(int *array) { int i; for(i = 0; i < 10; i++) { printf(" %3d ", *(array+i)); } printf("\n"); } void delay_500ms(void) { Sleep(500); } int main(void) { int i,j; int tick; int count = 0; while(array[count][0] != 0xAA || array[count][1] != 0x55)//如果当数组第count行第0列等于0xAA,或者第count行第1列等于0x55时,那么就退出,否则就循环执行遍历数据 { to_Q112_cmd_designator_LED((int *)(&array[0][0]+count*10) );//以首元素每次向后偏移10个字节 delay_500ms(); count++; } return 0; } 运行结果: 3 0 0 0 0 0 2 0 0 0 12 0 0 0 0 0 4 0 0 0 16 0 0 0 0 0 8 0 0 0 96 0 0 0 0 0 16 0 0 0 128 1 0 0 0 0 32 0 0 0

    时间:2018-04-27 关键词: C语言 嵌入式

  • 浅谈单片机上操作系统的利弊

     早在20世纪60年代,就已经有人开始研究和开发嵌入式操作系统。但直到最近,它才在国内被越来越多的提及,在通信、电子、自动化等需要实时处理的领域所日益显现的重要性吸引了人们越来越多的注意力。但是,人们所谈论的往往是一些著名的商业内核,诸如VxWorks、PSOS等。这些商业内核性能优越,但价格昂贵,主要用于16位和32位处理器中,针对国内大部分用户使用的51系列8位单片机,可以选择免费的uC/OS-II。 uC/OS-II的特点 1.uC/OS-II是由Labrosse先生编写的一个开放式内核,最主要的特点就是源码公开。这一点对于用户来说可谓利弊各半,好处在于,一方面它是免费的,另一方面用户可以根据自己的需要对它进行修改。缺点在于它缺乏必要的支持,没有功能强大的软件包,用户通常需要自己编写驱动程序,特别是如果用户使用的是不太常用的单片机,还必须自己编写移植程序。 2.uC/OS-II是一个占先式的内核,即已经准备就绪的高优先级任务可以剥夺正在运行的低优先级任务的CPU使用权。这个特点使得它的实时性比非占先式的内核要好。通常我们都是在中断服务程序中使高优先级任务进入就绪态(例如发信号),这样退出中断服务程序后,将进行任务切换,高优先级任务将被执行。拿51单片机为例,比较一下就可以发现这样做的好处。假如需要用中断方式采集一批数据并进行处理,在传统的编程方法中不能在中断服务程序中进行复杂的数据处理,因为这会使得关中断时间过长。所以经常采用的方法是置一标志位,然后退出中断。由于主程序是循环执行的,所以它总有机会检测到这一标志并转到数据处理程序中去。但是因为无法确定发生中断时程序到底执行到了什么地方,也就无法判断要经过多长时间数据处理程序才会执行,中断响应时间无法确定,系统的实时性不强。如果使用uC/OS-II的话,只要把数据处理程序的优先级设定得高一些,并在中断服务程序中使它进入就绪态,中断结束后数据处理程序就会被立即执行。这样可以把中断响应时间限制在一定的范围内。对于一些对中断响应时间有严格要求的系统,这是必不可少的。但应该指出的是如果数据处理程序简单,这样做就未必合适。因为uC/OS-II要求在中断服务程序末尾使用OSINTEXIT函数以判断是否进行任务切换,这需要花费一定的时间。 3.uC/OS-II和大家所熟知的Linux等分时操作系统不同,它不支持时间片轮转法。uC/OS-II是一个基于优先级的实时操作系统,每个任务的优先级必须不同,分析它的源码会发现,uC/OS-II把任务的优先级当做任务的标识来使用,如果优先级相同,任务将无法区分。进入就绪态的优先级最高的任务首先得到CPU的使用权,只有等它交出CPU的使用权后,其他任务才可以被执行。所以它只能说是多任务,不能说是多进程,至少不是我们所熟悉的那种多进程。显而易见,如果只考虑实时性,它当然比分时系统好,它可以保证重要任务总是优先占有CPU。但是在系统中,重要任务毕竟是有限的,这就使得划分其他任务的优先权变成了一个让人费神的问题。另外,有些任务交替执行反而对用户更有利。例如,用单片机控制两小块显示屏时,无论是编程者还是使用者肯定希望它们同时工作,而不是显示完一块显示屏的信息以后再显示另一块显示屏的信息。这时候,要是uC/OS-II即支持优先级法又支持时间片轮转法就更合适了。 4.uC/OS-II对共享资源提供了保护机制。正如上文所提到的,uC/OS-II是一个支持多任务的操作系统。一个完整的程序可以划分成几个任务,不同的任务执行不同的功能。这样,一个任务就相当于模块化设计中的一个子模块。在任务中添加代码时,只要不是共享资源就不必担心互相之间有影响。而对于共享资源(比如串口),uC/OS-II也提供了很好的解决办法。一般情况下使用的是信号量的方法。简单地说,先创建一个信号量并对它进行初始化。当一个任务需要使用一个共享资源时,它必须先申请得到这个信号量,而一旦得到了此信号量,那就只有等使用完了该资源,信号量才会被释放。在这个过程中即使有优先权更高的任务进入了就绪态,因为无法得到此信号量,也不能使用该资源。这个特点的好处显而易见,例如当显示屏正在显示信息的时候,外部产生了一个中断,而在中断服务程序中需要显示屏显示其他信息。这样,退出中断服务程序后,原有的信息就可能被破坏了。而在uC/OS-II中采用信号量的方法时,只有显示屏把原有信息显示完毕后才可以显示新信息,从而可以避免这个现象。不过,采用这种方法是以牺牲系统的实时性为代价的。如果显示原有信息需要耗费大量时间,系统只好等待。从结果上看,等于延长了中断响应时间,这对于未显示信息是报警信息的情况,无疑是致命的。发生这种情况,在uC/OS-II中称为优先级反转,就是高优先级任务必须等待低优先级任务的完成。在上述情况下,在两个任务之间发生优先级反转是无法避免的。所以在使用uC/OS-II时,必须对所开发的系统了解清楚,才能决定对于某种共享资源是否使用信号量。 uC/OS-II在单片机使用中的一些特点 1.在单片机系统中嵌入uC/OS-II将增强系统的可靠性,并使得调试程序变得简单。以往传统的单片机开发工作中经常遇到程序跑飞或是陷入死循环。可以用看门狗解决程序跑飞问题,而对于后一种情况,尤其是其中牵扯到复杂数学计算的话,只有设置断点,耗费大量时间来慢慢分析。如果在系统中嵌入uC/OS-II的话,事情就简单多了。可以把整个程序分成许多任务,每个任务相对独立,然后在每个任务中设置超时函数,时间用完以后,任务必须交出CPU的使用权。即使一个任务发生问题,也不会影响其他任务的运行。这样既提高了系统的可靠性,同时也使得调试程序变得容易。 2.在单片机系统中嵌入uC/OS-II将增加系统的开销。现在所使用的51单片机,一般是指87C51或者89C51,其片内都带有一定的RAM和ROM。对于一些简单的程序,如果采用传统的编程方法,已经不需要外扩存储器了。如果在其中嵌入uC/OS-II的话,在只需要使用任务调度、任务切换、信号量处理、延时或超时服务的情况下,也不需要外扩ROM了,但是外扩RAM是必须的。由于uC/OS-II是可裁减的操作系统,其所需要的RAM大小就取决于操作系统功能的多少。举例来说,uC/OS-II允许用户定义最大任务数。由于每建立一个任务,都要产生一个与之相对应的数据结构TCB,该数据结构要占用很大一部分内存空间。所以在定义最大任务数时,一定要考虑实际情况的需要。如果定得过大,势必会造成不必要的浪费。嵌入uC/OS-II以后,总的RAM需求可以由如下表达式得出: RAM总需求=应用程序的RAM需求+内核数据区的RAM需求+(任务栈需求+最大中断嵌套栈需求)·任务数 所幸的是,uC/OS-II可以对每个任务分别定义堆栈空间的大小,开发人员可根据任务的实际需求来进行栈空间的分配。但在RAM容量有限的情况下,还是应该注意一下对大型数组、数据结构和函数的使用,别忘了,函数的形参也是要推入堆栈的。 3.uC/OS-II的移植也是一件需要值得注意的工作。如果没有现成的移植实例的话,就必须自己来编写移植代码。虽然只需要改动两个文件,但仍需要对相应的微处理器比较熟悉才行,最好参照已有的移植实例。另外,即使有移植实例,在编程前最好也要阅读一下,因为里面牵扯到堆栈操作。在编写中断服务程序时,把寄存器推入堆栈的顺序必须与移植代码中的顺序相对应。 4.和其他一些著名的嵌入式操作系统不同,uC/OS-II在单片机系统中的启动过程比较简单,不像有些操作系统那样,需要把内核编译成一个映像文件写入ROM中,上电复位后,再从ROM中把文件加载到RAM中去,然后再运行应用程序。uC/OS-II的内核是和应用程序放在一起编译成一个文件的,使用者只需要把这个文件转换成HEX格式,写入ROM中就可以了,上电后,会像普通的单片机程序一样运行。 结语 由以上介绍可以看出,uC/OS-II具有免费、使用简单、可靠性高、实时性好等优点,但也有移植困难、缺乏必要的技术支持等缺点,尤其不像商用嵌入式系统那样得到广泛使用和持续的研究更新。但开放性又使得开发人员可以自行裁减和添加所需的功能,在许多应用领域发挥着独特的作用。当然,是否在单片机系统中嵌入uC/OS-II应视所开发的项目而定,对于一些简单的、低成本的项目来说,就没必要使用嵌入式操作系统。

    时间:2018-04-25 关键词: 操作系统 单片机

  • 从单片机到嵌入式

     1、什么是单片机? 单片机是一个控制系统,接收管脚中断输入,进行一些简单的逻辑操作,对内存或flash进行访问,再输出到管脚 2、什么是嵌入式? 嵌入式有linux内核 linux内核功能有:进程管理、内存管理、文件系统管理、设备驱动、网络管理 3、单片机和嵌入式有什么共同点? 都是靠中断驱动,嵌入式是高级的单片机 4、单片机和嵌入式有什么不同点? 嵌入式进化更加高级,充分利用了中断功能 进程管理:通过时钟中断,制造时间片,通过时间片造成多进程可以切换; 内存管理:做了虚拟内存,主要是ram 文件系统管理:组织了文件,主要是flash 设备驱动:靠中断 网络管理:著名的协议栈 5、嵌入式linux内核是一直运行吗? 是,0号进程死循环,控制电源,降频;定时的时钟中断到来,会调度优先级最高的程序,没有其他程序就调用0号进程,也就是IDLE

    时间:2018-04-25 关键词: 单片机 嵌入式

  • 单片机连接蓝牙4.0心得分享

     最近公司要搞一个智能硬件,通过APP连接硬件,发指令达到某些目的,对于从没有接触过蓝牙的小白,简直是两眼一抹黑,于是从网上找例子,找攻略,例子和代码都不是自己想要的,于是只能求助于谷歌API,拿着某翻译,一个个对着看,终于调试成功了,下面直接上思路及代码。 1、从谷歌官网下载一份demo(通用的),对于任何串口,只要符合规范,这个demo都能调试。 2、谷歌官方代码共有4个类,其中两个比较重要,如下: BluetoothleService 蓝牙服务:里面有蓝牙的连接,写入命令后,蓝牙所返回的协议(这个协议是厂家给你的) DeviceControlActivity 设备控制类:连上蓝牙后进入这个界面,会出现一大堆服务,及服务的特征 3、了解两个类,接下来我们要连上蓝牙给单片机发送指令,首先打开DeviceControlActivity类,找到如下代码: //如果该char可写 if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) { LayoutInflater factory = LayoutInflater.from(parent.getContext()); final View textEntryView = factory.inflate(R.layout.dialog, null); final EditText editTextName = (EditText) textEntryView.findViewById(R.id.editTextName); final EditText editTextNumEditText = (EditText)textEntryView.findViewById(R.id.editTextNum); AlertDialog.Builder ad1 = new AlertDialog.Builder(parent.getContext()); ad1.setTitle("WriteCharacteristic"); ad1.setView(textEntryView); ad1.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int i) { byte[] value = new byte[20]; value[0] = (byte) 0x00; if(editTextName.getText().length() > 0){ //write string WriteBytes= editTextName.getText().toString().getBytes(); }else if(editTextNumEditText.getText().length() > 0){ WriteBytes= hex2byte(editTextNumEditText.getText().toString().getBytes()); } characteristic.setValue(value[0], BluetoothGattCharacteristic.FORMAT_UINT8, 0); characteristic.setValue(WriteBytes); mBluetoothLeService.writeCharacteristic(characteristic); } }); ad1.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int i) { } }); ad1.show(); } 以上这段代码就是写入命令的代码,起初我在这里栽了跟头,发现一件事,直接输入命令,此处的返回和协议文档是对不上的,于是我做了如下修改: if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) { byte[] bytes = hexStringToBytes("XXXXXXXXXXXX"); // characteristic.setValue(new byte[]{0xXX,0xXX,0xXX,0xXX,0xXX, (byte) 0xB2, (byte) 0xXX}); characteristic.setValue(bytes); boolean status = mBluetoothLeService.writeCharacteristic(characteristic); Log.e("shjysoft_info","状态:"+status); } 先把协议的16进制的字符串变成字节,然后放到特征里面,写进去,然后就成功了,但是没有接触过蓝牙的朋友会有疑问,给哪个服务哪个特征写,这边我也遇到 过,我跑过去问前辈们,前辈们说了一句,一个一个试,没错,你一个一个点,哪个返回正确就是哪个

    时间:2018-04-25 关键词: 蓝牙 单片机

  • 每天看一遍!给陷入迷茫工程师的一封信

     相对同时刚出校门同学从事其它行业而言优厚的薪水,以及不断学习更新的专业知识不仅仅让你感到生活的充实,更满足了你那不让外人知的虚荣心。在刚出校门的几年中,你经常回头看看被你落在后面的同学们,在内心怜悯他们的同时,你也会对自已天天加班的努力工作感到心里平衡:“有付出才会有回报”这句话在那几年中你说的最多,不管是对自已的朋友们还是自已的爱人。第二句最常说的话是对公司的领导:“不行我就走人!”,实际上你也真的走过几回。对了,在这几年中,因为你的经济条件不错,你开始买房、开始谈恋爱、结婚、开始有了自已的小孩。有时候你会对自已说再过两年就去买车。当然其中可能有许多大件是需要分期付款的,但你对前途充满了信心,你确信认为这种日子会永远的持续下去,即使不是变得更好的话。 日子总是在这种平淡中一天天的过去,就在那么不经意间,你突然发现自已已经快30岁了,或者已经30了,莫名的,你心里会漫延着一种说不清楚的不安情绪,你好像觉得前途并非像前几年那样变得越来越好,你也忽然发现你以前所瞧不起的同学里好像已经有不少开着车的了,也有几个人住着比你还大的房子,好像房款还是一次付清的,你突然明白你现在的生活比起你的同学来最多是中游偏上了。工作中最让你感到心里不舒服的是,你越来越不敢对你的领导说不了,即使比你来的晚的同事升职或提薪,你也只是在私下与朋友们一起喝酒时才敢发发牢骚,在头的面前你的声间越来越小、笑脸是越来越温柔。 你终于开始迷茫“再过几年我会是在干什么呢?”,这句话常常出现在你的心里。 计算机开发工作,是一种以年轻为资本的工作,说句通俗点的话是“吃青春饭的”,嗯,这句话好像在一种特别的行业也听到过。 其标志就是一:工作的时间性非常强,一个开发项目被定的时限通常是很紧张的,更有甚者,有些号称开发管理的书里面还非常卑鄙的号召将一个项目切成多个小片,每个小片都定一个叫“里程碑”的东东来严格跟踪开发进度,加班加点在其它行业是需要加班工资的,而在开发行业,加班工资好像还没见到几个公司发过,是啊,反正有时间限制着,你干不完我再找你算账.所以开发工作通常有着其它工作所没有的精神上的压力。 一旦一个人步入而立之年,因为家庭和孩子的负担,加上精力上面的衰退,加班工作时间变得越来越少,这点让很多老板们感到:这些人已经老了,不好用了。指示人事部门:“以后招开发人员限制在30岁以下!”,相对而言硬件开发会年龄方面限制会稍好一点点,但也是五十步笑百步。还有一个很重要的一点就是:计算机这个烂东东实在是进步的太快了,前两年买的顶级配置电脑,现在怎么看怎么像废品,这还是小事,更可气的是好像每天都需要学习新的知识,刚毕业时只会书本上的PASCAL,学会了用腐蚀的办法来做电路板,一上班就开始学习TURBOC和TANGER2.0,刚刚学会,还没来得及高兴,马上开始学Borland C++和Protel3.0,好不容易学会了,却发现需要学习VC和Protel98了。单片机也是啊:Z80的指令背的很熟,工作中没来得及用就要学8031,好好学吧,本来想着这辈子就吃它了,又发现又出来什么PIC、DSP、CPLD、FPGA、ARM等等....这还不包括中间要学一大堆74系列、4000系列、XX系列...IC卡居然里面还有CPU卡..如果学习的知识里每个字都能变成一分钱,我想所有的开发工程师都是腰缠万贯的富翁。 一眼看去,这种日子好像见不到头,年轻时乐此不彼,但现在你一定对自已能坚持到什么时候感到怀疑了。我们都玩过像仙剑奇侠传这样的RPG游戏,刚开始时你只是一个一名不文的少年,随着你去打怪物、捡宝贝、学秘芨,最后终于有一天你会变成一个大英雄!那么你在实际生活中过得比那些小侠们还辛苦,为什么成不了一个生活中的大侠呢?呵呵,原因在这里:因为开发工作是邪门功夫,它虽然可以让你速成的变成小资,但它最大的特点是经验不积累!日新月异的知识更新,让你总是感到自已在退步,你就像在RPG中的主人公,开始时就给了你一把好剑和好盔甲,而且让你的级别很高,但让你的经验不累积,虽然刚开始打小怪物时你觉得自已很爽,但越到后来,你会发现你会死的很惨!比较一下你与其它非开发行业的同学你就可以知道了,例如和你学医的同学比起来。套用岳不群他老人家说华山剑宗和气宗的区别那段话:前十年你比你那些学医的同学收入和地位要好的多,但十年以后你和他基本上各方面都会持平,而二十年以后你的各方面远远不能与你学医的同学相提并论!嗯,你已经开始不笑辟邪剑法了吧。 “敢问路在何方?路在脚下...”,不过猴兄和八戒兄这么认为是可以的,你呢? 总结了许多开发朋友在30岁以后的生活之路,让我们一起看看开发人员“路在何方?”那么开发人员在30岁以后都干些什么呢? 其路一:继续做你这个很有“前途”的职业吧! 偶掰着脚指头仔细数了数,发现还真的有很多朋友在30岁以后还在从事开发工作,我这里说的从事,是指你还需要天天在电脑边上编程序和画电路板,与你手下是否有几个小兵无关,也与你是否头上顶着什么项目经理、主任工程师的帽子无关,只要你还需要亲自开发,你就属于这一类。其中有个年龄最大的朋友是63年的,从事医疗仪器的开发工作,35岁左右还在从事软硬件开发工作的仍有一大堆,分析这些仍然从事开发的朋友,基本上都有以下特点: 1 痴迷工作或者痴迷电脑,晚上八点到十二点的这段时间,基本上是在电脑桌或工作台前渡过的。 2 不喜欢与人交住,朋友很少,常联系的人不超过五个。 3 与朋友交往时谈工作多,但一般不主动谈钱。 4 体型偏胖或偏廋,不在正常区间。 5 无未来计划,对五年后自已生活怎么样、从事什么工作说不清楚。 6 俭省,从不乱花钱。 即使你是还不到30岁的开发人员,你也可以看看自己对以上几条是否符合,是否会在30岁后还从事开发职业,四条疑似,五条以上基本确诊你也是这类型的人。 这些朋友们通常报着过一天是一天的态度生活,到了这个年龄,也不敢再轻易的换工作了,年轻时的锐气慢慢的也消退了。唯一不变的希望是有一天从天上掉下来一大堆钱把自己砸伤。说实在话因为他们的性格所限,基本上可以确定他们以后不可能在职场上获得更好的发展,当个小头头,带几个人开发已经是他们发展的顶点。至于以后的人生之路,不仅他们自己迷茫,可能上帝也正在头痛。 不过像这类朋友,偶很奇怪的发现:他们的小孩都是儿子!不知是偶然还是有什么其它说法。 简单建议:要改变命运,先改变性格:坚持半年晚上不从事工作、游戏及电视,用此时间与人交往,你的人生会有改变。 其路二:转行从事技术支持、行政或生产等工作还有一些朋友,从事了几年的开发工作,因为自已并非特别的爱好,或者领导上面的强制工作安排,他们转到了技术支持、服务或行政等工作,至少当时从表面上看起来,他们的薪水较开发要少一些,但真正的统计这些人,发现他们之中有半数的人获得了更好的发展,升职为服务部经理或行政经理等职,最历害的一个朋友已升职为总经理助理,进入高层。 这类朋友当时转行通常并非自已志愿,属被逼无奈或者其它原因,但显然,拥有专业知识技术的他们显然在非技术部门中鹤立鸡群,遇到什么事情他们均可从专业的角度提出建言,久而久之,他们获得更多的升职和加薪机会也就不足为奇。 因为不从事开发,所以经验开始积累,这类的职业通常会给你一个很安定的感觉,你到30多岁后会发现这类职业反而比开发工作更容易获得新的工作机会。 简单建议:你如果确定在开发部无法获得很好的发展机会,不妨转到其它几个部门试试,换个活法,钱少点就少点吧,机会多。 其路三:开发管理 如果你现在已经是总工或开发部经理,或者你眼看就有机会被提升为这类职务,那么恭喜你,你走的是从“弼马温”到“斗战胜佛”这条金光大路,你不仅拥有很高的专业技能,而且很显然,你也有着很强的人际交往能力,你这类人根本不需要对未来有着任何的担心,你在即使一无所有的时候也很容易白手起家。 你这种人算是练辟邪剑法练成了仙,嗯,我无话可说。 你是不是这类人也很容易区别,就像围棋二十岁不称国手终身无望一样,你应该在工作三、四年以后,也就是说二十七岁左右就会发现自已工作中指手划脚的时间比亲自开发的时间要多了,而且大多数这类人在这个年龄手下应该有“兵”了,相反的,如果你快30岁了还天天埋头于电脑前编程序和画板子,或者30多岁了你还没升到部门经理(虽然你总是觉得自已很有希望),基本上可以确定你不是这类人。好了,如果你确定你是这类人,那么你唯一的想法就是尽快爬上中层和高层,因为有时候人生偶然性太大,不占住坑的萝卜很有可能被人拔出来! 简单建议:天天去你的老板家里面拖地和擦桌子! 其路四:出国或考研 有两个搞开发后出国的朋友,其中一个甚至打工打到了一个小公司总工的位置,数据库和软件方面水平巨牛,但仍感觉心里不踏实,于是将自己工作多年的钱忍痛掏出来,出国费加上机票大概将自已辛苦所攒的银子花完,然后又借了一些钱,在02年身上揣着一万美元跑去了加拿大,在加拿大不停的重复找工作,换工作,然后再找工作的循环,找的工作基本上与计算机无关,不过工资总是在1500加元左右,呵呵,折成人民币与他在国内打工拿的基本上差不多,不过租个地下室就花了300加元,然后吃吃喝喝,再买个电脑上上网这类的,基本每月平均还要倒贴一点。前段时间给我的邮件里说,现在身上花的差不多只有5、6000美元了,准备开个小公司,看看能不能往国内倒腾点东东,做最后一搏。另外一个朋友去澳州,时间稍早一些,先是大概摘了一年多的葡萄,后来总算找了个技术工作,每天的工作是画机械图纸,收入还算不错 将近3000澳元,买了个旧车,也算是过上了资本主义生活。不过前年回来一趟,唯一的感叹就是:在国外拿2000美元的生活,绝对不如在国内拿5000人民币的生活舒服。 也有两个考研的朋友,不过其中一个严格的说不是做开发的出身,偏重于市场方面的工作性质,不过我的朋友里面考研的不多,只好凑两个人说说,一个考研后在北京找了个工作,每个月5、6000元钱,但还是做开发,生活仍然与没考研之前没有任何的改变,前途仍然没见到什么大亮的光,还是搞不清楚以后再干些什么,标准的过一天算一天了。另外一个考研后在大学里面找了个工作,工资虽然比他原来打工少了不少,但毕竟终身有靠,稳定了下来,也算修成了正果,这位哥们心情一放松下来,也开始有时间琢磨着业余时间自已做点什么,好像现在慢慢的也开始有了点眉目。 简单建议:这两条路,对开发人员来说都不算是很好,出国十年前是好事,现在难说,考研能成功转行的概率恐怕也不是很大,多半仍然去搞开发,只不过研究生可以多干几年罢了。 其路五:转行到市场 绞尽脑汁的想想,我所知道的人之中只有两个开发人员去了市场,这两个人都不能说是朋友,认识而已。他们都是主动要求去了市场,结果是这两个人均在市场都是干到一年左右,然后都自已开公司了。呵呵,很奇怪,极高的转行成功率!不过仔细想想,我对这两个人的思路佩服的五体投地。能下决心仍掉每月5、6000元的开发职位,从事一个自已并不熟悉的岗位,每月拿个2000多元+提成,但提成那是说不清楚的事情,这个决定,只能让人感觉到他们对自已前途清晰的把握和老谋深算的心机。而且他们不去服务不去生产,挖空心思说服领导去市场(市场部门与开发部门通常是一个公司的核心部门,进入其实并不容易),可以说是有着长远的考虑的。有技术了,再与客户交成朋友,马上就会产生很大的机遇应该是正常的事情。 有实力,有心机,也有着很强的决心力,这种人恐怕早在大学毕业时或更早的时候就已经决定了自已的人生之路,他们的每一步路在若干年前早就计划周全,现在看起来:学会技术->进入市场->寻找商机->开公司,一条多么清楚的人生之路。但就像我们上小学中学时,所有人都知道上大学是我们最清楚的人生路一样,最后只有少数人才能真正达到目标(当然,现在扩招的历害是另外一回事,我是说我们那个时候,也就是:“很久很久以前,当我像你那么大的时候”)。 简单建议:你若是这类人,我的建议是:...嗯?....那个你.你,你别走啊,我还有个事想请你赞助一下啊..... 其路六:开公司自已干 呵呵,看到这一条,发现你的眼睛已经圆了,你肯定千百次的想过这个事情吧,咳咳,其实我从事开发的时候也是天天梦想着这种事情。总想着过两年找个机会就自已干,这个梦想一年又一年的折磨着你也给着你希望。看看吧,开发后来开公司的还真的不少,里面有成功的也有很多失败的,通常开公司都是几个人合伙开始的,有做技术的,有做市场的,几个人一拍即合、狼狈为奸,共同策划了这一个大活动。一般说来能让这几个人下决心走出这一步,产品肯定是先进的,甚至是国内独一无二的,市场也是很大的,负责市场的那个哥们通常会拍着胸保证可以卖出去,并悄悄地告诉你他在某主管领导是他小舅子的同学的二叔,肯定没问题。于是你们几个人找地点、注册执照、买了几个破桌子,再攒了两台电脑,每个人又凑了几万银子,公司开张了! 产品很快出来了,市场的哥们也不负重望,有几个客户表示要试用了,一切看起来都是如此的正常,“.......你坐在老板桌前,不停的有人来汇报工作或者找你签字...人进人出中...你又想起公司再穷也不能只有一把椅子的故事.....”你在梦中笑出声来。 是如此的顺利,你们很快就有单子了,很快的单子让你们凑的那点钱不够了,你们很高兴的每个人又增加了投入,拿出钱时你眼泪汪汪的数着钱说:“这就是我那生蛋的母鸡啊”。你们的产品确实不错,市场也经营的很好,客户慢慢的多了起来,单子来的时候一笔接着一笔,你每天都处于兴奋之中,唯一美中不足的是好像客户回款总是会拖一些日子,不过客户给你保证说:过几天,过几天就付给你们,因为回款总是在计划外,所以你们为了资金的流畅运行又凑了一些钱,这个时候你有一些心事了,因为你的存款折上面的数字已经快趋向于零了。“没事,过两个月等回款了一切都OK了,谁干事业不吃点苦呢?”你这么安慰着自已又投入到工作中去,资金总是在回款和生产经营费用之间走着一个窄窄的小木桥,你的账上总是没有太多的钱,扩大了的公司规模和许多意外情况,使你又一次、二次、三次的与合作者们再次投入了自已的资金,当然,后来的钱你可能已经是借的了..... 终于有一天,你的会计再一次告诉你,老板啊,账上又没现金了,吃过多次苦头的你终于下决心开始重视资金的运行了,你裁掉了一些不必要的人手,减少了开发的投入,要求市场人员签单的时候必须予付XX%的款,回扣也必须等收过款后再付,同时也开始对产品的生产成本开始进行控制。 时间一天一天的过去,因为竟争对手的产品也对你的产品进行了仿造,你的产品慢慢变得不再先进,市场人员开始埋怨公司的合同资金方面规定太严格,不好签单,生产成本的下降通常也导至产品毛病的增多,客户也开始埋怨你的服务人员不能及时进行服务。 终于有一天,你重新走进了人才交流中心,以前你是来招人的,现在你拿着自已的简历开始寻找一个工作 ...... 公司的成功与否,与产品有关,与市场有关,但更重要的是与资金有关,产品与市场都可以通过资金来弥补,而却没有任何东西可以代替 资金,凡是倒下的公司,99%与资金链的断裂有关。在你决定要开公司以前,先估计一下你公司支持一年所需要的资金数额,包括人工费,生产,场地,广告宣传、市场费用、甚至电、水费等等等等,把你所想到的一切加在一起,得出的值就是..慢..如果你没有实际的开过公司的经验,你需要将此数字乘3,然后就是你开公司一年最少需要的费用,呵呵,公司的实际运营所需要的钱是你想像的3倍以上,你要是不信我也没办法。 简单建议:开公司前最重要的是先确立你后续的资金来源!也就是说钱不够了怎么办?---因为你投入的钱肯定会不够的。 其路七:第二职业 这类的朋友有不少,他们没有脱离开发工作,但是在业余时间又不停的接项目或者在卖产品,在单位里面他们显得并不出众,比起其它人来说他们属于最不愿意加班的一类.为此他们白天通常工作很勤奋.这类人也许不一定可以挣很多钱,但平均下来他们一年之中通常都可以比同事们多挣个几万元.有时候比上班拿得还多.但令人疑惑的是,这类人在生活中更加注重稳定,基本上没见到他们跳过蹧,即使私下里面已经开了个小公司,他们通常也不会辞职. 你的旁边有没有这类人呢?分辨他们很容易: --电话很多,而且更愿意来电话时离开办公室找个没人的旮旯通话.神秘兮兮给人一种"这家伙是不是有二奶啊?"的感觉的人,通常是这类人。这类人是女性最佳的选择对象:很顾家,不象那些富人容易花心,而比起一般人来说,他们收入相对要高得多。但总结了一下几位这类的开发朋友:也得出了一个令人沮丧的结论:这种人通常个子不高,体形类似桶状..... 简单建议:这好像是开发人员最佳的出路了,但比较丰厚的收入通常让这类人不愿意去冒风险....到现在为止我所认识的这类人还没有一个真正算是成功的。 好了,虽然偶的经历远远说不上丰富,也没有什么成功之处可以自满的,但或许因为比其它朋友痴长了几岁,见过的人可能会稍多一些,所 以斗胆写出了以上的一些文字,让您掉牙了。 下面是偶走过开发这条路上总结出来的一点心得,你可以不看,但看了就千万别把嘴咧的太大: 一、不管是给别人打工还是自已干,都要全心全意的工作,因为你所做的任何一点工作都会让自已的人生多一点筹码,这一点最最重要!这样的例子我至少可以举出两起,优秀的开发人员被其它新公司挖走,并给一定的股份,成为新公司的股东的例子。当时与这样的开发人员一个部门同时工作或更早工作的有许多人,他们平时经常偷点懒,能少干点工作就少干点,有时候还笑话那个平时努力工作的人傻,几年过去了,究竟谁比谁傻? 二、多与市场人员交朋友,你接触他们时可能总会觉得他们知识比你少,甚至素质比你低,可能比你还有点黄。但实际上他们比你更懂这个社会!参加到他们这个圈子中去,和他们一起赌赌钱、一起聊聊天、一起洗洗桑拿、一起.....你会通过他们接触到另外一个世界。 三、机会远比钱重要,挣不挣钱在年轻时并不是特别重要!不论是在实际生活中还是在网上或其它地方,如果有机会参与到除本职工作外的一些项目或产品的开发中(包括你的朋友拉你去做点小生意之类的非开发性质的工作),那怕是帮忙的性质,也要积极介入,至少你会交到很多的朋友,这样你的人生会多出很多的机会。

    时间:2018-04-25 关键词: 工程师

  • 嵌入式系统C语言重点语法const、volatile、static、堆栈等的意义及用法

    在单片机应用中,堆栈是个特殊的存储区,主要功能是暂时存放数据和地址,通常用来保护断点和现场。 要点:堆,队列优先,先进先出(FIFO—first in first out) 。 栈,先进后出(FILO—First-In/Last-Out)。 const: const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。 const关键字的作用主要有以下几点: (1)可以定义const常量,具有不可变性。 例如: const int Max=100; int Array[Max]; (2)便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。例如: void f(const int i) { ………} 编译器就会知道i是一个常量,不允许修改; (3)可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。 (4)可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。 还是上面的例子,如果在函数体内修改了i,编译器就会报错; 例如: void f(const int i) { i=10;//error! } 1 (5) 为函数重载提供了一个参考。 class A { ...... void f(int i) {......} //一个函数 void f(int i) const {......} //上一个函数的重载 ...... }; 1234 (6) 可以节省空间,避免不必要的内存分配。 例如: #define PI 3.14159 //常量宏 const doulbe Pi=3.14159; //此时并未将Pi放入ROM中 ...... double i=Pi; //此时为Pi分配内存,以后不再分配! double I=PI; //编译期间进行宏替换,分配内存 double j=Pi; //没有内存分配 double J=PI; //再进行宏替换,又一次分配内存! 123456 const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。 (7) 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

    时间:2018-04-25 关键词: C语言 嵌入式

  • 操作系统与裸机的区别,stm32能运行什么操作系统?

     我们在学习stm32到一定阶段可能会了解操作系统,然后便有这种问题产生,下面我就来粗略说说“操作系统与裸机的区别,以及stm32能运行什么操作系统,能运行linux系统吗”等问题。 操作系统与裸机的区别 裸机运行的程序代码,一般由一个main函数中的while死循环和各种中断服务程序组成,平时CPU执行while循环中的代码,出现其他事件时,跳转到中断服务程序进行处理,没有多任务、线程的概念。 而引入操作系统后,程序执行时可以把一个应用程序分割为多个任务,每个任务完成一部分工作,并且每个任务都可以写成死循环。操作系统根据任务的优先级,通过调度器是CPU分时执行各个任务,保证每个任务都能够得到运行。若调度方法优良,则可使个任务看起来是并行执行的,减少了CPU的空闲时间,提高了CPU的利用率。由操作系统的任务管理衍生出相应的CPU管理、内存管理,它们分别负责分配任务对CPU的占有权和管理任务所占有的内存空间。在linux操作系统中,还具有文件管理、I/O设备管理的功能。 stm32能运行什么操作系统,能运行linux系统吗? 首先操作系统有两种:一种是用MMU(Memory Managenent Unit ,即存储管理单元)的,另一种是不用MMU的。 用MMU的是Windows、 MacOS、 Linux 、Android; 不用MMU的是FreeRTOS 、VxWorks 、 ucLinux、uc/OS. 其次CPU也有有两种 :带MMU的和不带MMU的。 带MMU的有 Cortex-A、ARM9 、ARM11系列。不带MMU的有 Cortex-M系列 而我们知道STM32是 Cortex-M3系列的…所以目前还不可能运行Linux操作系统,但是stm32可以运行uc/OS、ucLinux、FreeRTOS 、VxWorks等操作系统。其中uc/OS操作系统是开源代码,且小巧而严谨,具有很高的实时性,可以作为学习linux等高级操作系统的基础,实际项目中也经常使用uc/OS开发。

    时间:2018-04-25 关键词: 操作系统 STM32 单片机

  • 单片机裸机开发经验

     在论坛里见到好多朋友学习裸机的时候都有一个习惯——做裸机开发时,过度依赖天嵌的裸机测试程序。怎么说呢,我觉得这样不是很好。尤其是对于一个新手。 也许是学习单片机出身的原因,我有一个毛病,就是对别人的代码不放心、凡事非得扣到底层。 一开始我看天嵌的裸奔三部曲,有一个体会——越看越迷茫。尤其是简单地修改了天嵌的程序,实现了显示几个自定义图片的时候。这里也算是给天嵌提一个建议吧。一般来讲,新手看到这里的感觉就是特迷茫:难道这就是学裸机程序吗?修改几行C代码?天嵌手册里说这样会迅速建立成就感,可是我丝毫没有。反而感到的是强烈的不安。毕竟天嵌的裸机程序对于一个新手来说太庞大,甚至会搞不清文件之间的关系。我们现在做的就是简单地修改几行现成的代码,然后看看效果。我就在想,此时我只会修改几行代码。底层硬件、ARM是如何启动的、启动代码2440init.s是如何支持ARM启动并跳转到C函数里的?这些东西都被天嵌的裸奔三部曲教程透明掉了,这些我都不会,我们只是做了做应用层的修改。而那些被透明掉的知识,现在完全都是依赖于天嵌的测试程序的。试想,一旦一天老板让我做一个新的东西,新的硬件配置,没有了天嵌裸机程序里的底层知识,我们将如之奈何?基本就废了吧。 也许是由于原先是搞单片机的缘故,所以总喜欢扣底层,做Linux或者WinCE上层应用的朋友也许会觉得我在这里瞎折腾,做无用功。但是,对于从单片机转过来的人来说,我说的这些是最重要的——他们要搞清楚ARM是如何工作的,如何用程序去控制硬件,如何靠自己的力气搭建出来一个裸机程序。和做上层的人不一样,做底层的人就喜欢扣这些东西,因为这些东西如果搞不懂,那搞其上层来就会觉得发飘,或者说总是不知道地下发生了什么导致心里没底。最要命的是以后做Linux设备驱动的时候。由于对底层的认识不够,必将导致非常吃力! 这些天狂啃了一顿启动代码2440init.s。忽然意识到,裸机应该换一个方法学。 第一步、狂啃启动代码。 啃过之后你就会发现,原来大家在三星原版基础上改的,然后互相抄,有的甚至都抄错了。这可能是个痛苦的过程,你要找各种版本的2440init.s,但却是必经的。一旦走过,你会发现你对ARM底层就有了和以前不是一个深度的理解。以后做起开发来底气也就足了。这个过程里,你会遇到很多汇编的基础,杜春雷的那本《ARM体系结构编程》就是本很不错的材料。但是千万记住,你拿它当字典用就行,千万别运气下决心要从头到尾看完。不然你真不知道你是怎么死的。以前还有人说一定要通读三星手册,我觉得这跟杀人没什么两样。学习一定要有目的性。当学习启动代码遇到问题时,再去查汇编语法和三星手册时,学习时最快的,记得最牢的。如果漫无目的地通读。。。。就算最后你活下来了,你也不知道之前你都看了些什么。。。。 第二步、跟着启动代码跳转到C程序来。 这个过程就像搞单片机一样了。自己写自己的第一个跑马灯程序、蜂鸣器程序、按键中断程序、定时器、LCD etc etc etc etc etc。最后你再把自己写的所有的东西组合起来,构建成一个属于自己的裸机测试程序。经历过这个过程,你就会发现,原来ARM不是不可战胜的。原来,你已经一步一步踏实的走过来了。这个时候,你回头再看一眼天嵌的逻辑测试程序,你就会淡然一笑,哦,这个啊,我自己已经写出来了。 至此,所谓“成就感”才建立起来。至此,你才可以丝毫不依赖别人地做出自己的东西。至此,你才学到了真正的东西。 因此,在这里我诚恳地向天嵌提出建议。如果写裸奔教程,请从最底层写起。贵公司对启动代码的介绍少之又少。而完全是在对上层做文章。我想,对于一个ARM新手,不管他之前学没学过单片机,你让他过度依赖测试程序的框架做开发,他真的会因为底层基础不好而发飘,导致以后的全部开发都过度依赖现有的测试程序。从本质上讲,他还是没有学懂裸机。在没搞懂启动过程的前提下,就去学习裸机电子钟之类的东西,结果只有一个字——飘。 我知道天嵌写教程也要考虑篇幅,也不能面面俱到。面面俱到那真的是强人所难。但是不知道贵公司是否可以考虑换一个思路,换一种引导的方式,哪怕只是写一个启动代码的详细注释,已经如何建立一个启动代码+LED跑马灯程序,都足以给用户一个清晰的方向。以后的教程甚至不写,用户也会沿着思路,学会自己搭建起属于自己的东西,而不是搭建起建立再现有代码基础之上的东西。这样用户学到的东西才真正会变成自己的。 最后,想说选本好的教材,这很重要。不好的教材只能让你多走弯路。 我觉得阿南的那本《ARM Linux入门与实践》就很不错,我不是在做广告,真的不错。那里多一句废话不写,净捞干的。比如汇编部分,他只介绍了学习启动代码所必须掌握的一些指令和伪指令。其他没用的一概不写,不像有些书,就会抄DataSheet。 韦东山的《嵌入式Linux应用开发完全手册》对于裸机部分写得其实不是很好,他总喜欢在Linux下搞。而且中断那里写得非常不好。我们大多数人还是在ADS下搞的,于是我们一般还都是用启动代码来启动开发板的(搞裸机也不能太裸不是,启动代码都自己重新写就基本可以直接累死了),启动代码里的非常漂亮的两级向量表中断处理机制韦东山完全没用到。而且那本书每一章里知识高度浓缩,新手看了容易上头。而且,凡是号称什么什么全书的,往往不可能写得很全。嵌入式技术是一个庞大的体系,怎么可能一本书写全呢?如果号称全,则必然不精。 还有,有谁还看中嵌的视频的就别看了。首先我说,他们已经倒闭了,因为骗钱倒闭的。他们的质量很差,视频质量也很差。老师就是在念程序或者念DataSheet。讲启动代码的时候老师屁都不会,之前他们讲过汇编语法,讲到bootloader的时候,bootloader再干什么一点儿没讲,反而又领着学生复习汇编基本语法,这都忍了,可老师硬说bic指令是跳转指令。 还有,体系乱套。先讲Linux,然后将裸机。我都不知道他是不是先拉屎后脱裤子。这种东西最好别看。看完他的视频再看什么教程都没法学了。这个和吃完大便之后就再没食欲吃烤鸭是一个道理。 帖子有的地方有点儿攻击性,有点儿偏激。再次往误伤的同胞海涵。如果您觉得我扯了半天都是废话,您就当这是一阵风飘过,或者这是我半夜的梦话。。。

    时间:2018-04-25 关键词: 单片机

  • STM32的晶振,时钟稳定性要重视!!!

     最近看了不少网上网友的应用案例,在STM32晶振问题上不少都栽了跟头。我自己也碰见过一次。就是电容值搞错了。 ourdev有网友说:他的设备隔几天系统就出问题,系统时钟变慢。 ----------------------------------------有网友说: 国产的晶振,我们用在产品里吃过很多亏。发出去几百个货(出厂都检验合格), 到客户那里几个有时就不起振了(几个月后),后来改用进口的,从此不出问题了。哎! ---------------------------------------有网友说: 第一次遇到是忘了焊接22P的电容,板子可以工作,但是运行速度慢,但是晶振起振了, 示波器看波形有刺,想必是STM32认为外部晶振信号不好,自己用了内部的时钟,焊上22P电容, 波形变好,板子正常工作; 第二次是装在机器里面的板子,突然也是变慢了,以为是电源烤坏了晶振,因为电源比较热, 整机是全密封的,拆下晶振重新焊一个,OK,再没出过问题。 所以我认为晶振还是关键,STM32对晶振应该是有比较高的要求的,千万不要吝啬晶振上的成本。 -----------------------------------有网友说: 楼主的现象我也遇上过,可能是8M晶振失效或虚焊了,初始化时采用了内部时钟,慢了不少。 --------------------------------有网友说: 32.768晶振的负载电容类型需要 6P的,最好用4脚封装那种灰黑色的。 另外,如果是 RTC慢,就是32.768的问题。 如果是系统忽然变很慢,就是HSE部分,8M的那个有问题。 STM32 的自恢复能力还是很强的。 ---------------------------21IC有yewuyi 网友说: 国内量产型低价晶体,尚不能做到真正的5PPM,标5PPM,其实都是10PPM以上的。 ------------------21IC网友IJK: 给STM32配6PF的32768晶振,当然用官方推荐的最好,官方推荐了:Epson、KDS和JFVNY, JFVNY是北京晶宇兴公司的晶体。 STM32的官方开发板用的就是JFVNY的32k晶体。 --------------------------有网友说: 21IC的ispmcu网友也说他搞ISP下载时候,也有时候一次搞不成功,两次上电才OK。 -------------------------ourdev网友: 31楼的情况碰到过,原因是负载电容焊错了,换了就好了。当时不小心焊上了0.1uF的,导致无法起振, 自动启用内部的晶振,所以也就是楼主说的慢了好几倍,呵呵,换了正确的电容后,就一切正常,没有出现过问题。 如果31楼换了晶振电容后,仍然有问题的话,可能要考虑是否是电源噪声,电路板布局等的因素了 -------------------------------网友: 我用STM32,启动时候如果检测不到外部晶体 就让他抱错停止,没有让他自动切换内部震荡...... 网友: 国产晶振,这几年越来越差,是不争的事实。我现在用STM32,就出过几次晶振问题。一次是国产晶振不耐震动, 成品运输过程坏了不少,还以为是芯片问题,吓出一身冷汗,哪采购了可不少的量。一次是用了国产晶振后, 总线的频率有误差,外设工作不正常。这两个都是换了晶振解决。 还有一次比较怪异,做样品有10张板,就有一张的晶振焊下去是不起震的,其他的都没问题,该换过的都换过, 很怪异,后来也没深究。不知和LZ的原因有没有关系。 传统的51工作频率较慢,所以用劣质一点的晶振,工作还过得去。STM32要是跑72M ,晶振的误差就很可观了。 所以什不能省晶振 --------------------------------------网友: 既然楼主不回来结贴,我来结贴,我也遇到这种情况,其实就是外部晶振没有起振,而使用了内部晶振。 我是一个搞软件的,对硬件不熟悉,我仔细查看了一下晶振的配置代码,问题在选择外部晶振后, 要有个延时时间等待外部晶振起振。而这个延时时间是ST公司直接在固件库里设定了,就是等待了128个指令周期。 也许ST公司认为在这么长的等待时间下,晶振应该可以完全起振了。如果你把这个等待时间改的长一点就可以了, 如果还不可以,那就是晶振太差了,或者其他原因,自己找吧。 要改那个等待时间,打开stm32f10x_rcc.c 将 #define HSEStartUp_TimeOut        128      里的128改成一个大一点的数,我是改成了2000. 希望你们可以解决。 【博主注明】这个和我当时的方案是一样的。即便电容搞错了,将超时时间延长也是可以的。。。。 但是一定要认为这是不正常的情况,想想办法在产品上体现出来,例如用灯。 ========================= ------------------------------有网友: 你可以看一下代码,大多数人开始接触STM32F10x时,差不多都是使用的ST公司提供的代码例程,而在时钟配置那里有一句代码是 if(HSEStartUpStatus == SUCCESS) 就是如果外部晶振起振成功才会进行锁相环的设置,那么如果外部晶振没有起振成功也就不会设置锁相环了, 这样系统选择内部晶振后,因为没有对锁相环设置,所以你就会感觉到系统一下子慢了很多。实际上ST提供的这个例程是不够严谨的, 只对条件成立进行了处理,而没有对条件不成立进行相应的处理,才会出现这些问题。 对于内部晶振来说最大的缺点就是不够稳定,在出厂时是在25°C下校准的,如果工作环境很恶劣的话,不知道漂到哪去了, 但是ST仍然给我们提供了校准的办法,就是修改时钟控制寄存器,但是好像很少有人这么做。所以如果你要用到通信功能的话,为了保证波特率稳定,必须要用外部晶振。 看样子对STM32的时钟的稳定性问题真是要注意。 ----------------------------------------------------网友: 我已经用STM32F103C8T6设计了款工业级产品,使用了进口有源晶振,价格相当于片子2/3,体积和MCU差不多大。 高低温、静电、EFT、跌落、机械振动都测试过了,没有问题。为了你的产品量产后不纠结,大家都用有源的吧!! 不过另一款产品年用DSP F28027的板子用的是小日本NDK的无源晶体,按照PDF配置了负载电容,高温85°上电8小时,也没有发现有什么问题。 我觉得时钟稳定性和布板有重大关系,有源晶振的线路距离CPU要尽量短,同时两侧的覆铜要密集过孔接地。 无源晶体的两根线要尽量紧靠、对称,离CPU距离要尽量短,负载电容距离晶体要尽量近,最好不要用49S或者49U封装,用7050、5032的贴片好些。实在必须用49S或者49U的晶振,它的壳体必须用焊锡接地.

    时间:2018-04-25 关键词: STM32 晶振

  • 单片机入门概述,为何会发明单片机?

     很久以前,人类发明了数字。自此,人类社会发生了巨大的变化。有了数字,人们解决了很多问题。在数字的帮助下,人们学会了度量和计算,人们发明了温度计,发明了钟表,发明了直尺,发明了算盘……生活中原本模糊的概念,变的不再模糊,而是十分精确。 1870年以后,科学技术的发展突飞猛进,各种新技术、新发明层出不穷,并被迅速应用于工业生产,大大促进了经济的发展。第二次工业革命爆发了。在这次工业革命中,电力得到了广泛的应用。 之后人们发明了各种电子元器件,特别是电子管、晶体管以及后来集成电路的发明对人类社会产生了巨大的影响。 有句话说,懒人推动社会进步。这句话是有一定道理的。在科技不断发展的过程中,一方面,人们希望制造出一种机器,能帮助我们完成处理现实世界中的各种问题,让我们从重复而繁重的脑力劳动中解放出来;另一方面,往往是在军事上,由于种种原因需要在较短的时间内,完成一些像炮弹轨道计算,密码破译之类的任务,而人类的数字运算能力往往远达不到要求。 最初人们发明了算盘之类的计算工具,又有人发明了一些机械式计算机,通过齿轮传动等原理进行运算。而后,在电子技术飞速发展的情况下,人们发明了电子计算机。早期电子计算机采用大量电子管,十分庞大,需要消耗很多电量,操作也非常复杂。如1946年发明的“埃尼阿克”电子计算机,占地面积170平方米,重达30吨,耗电量高达150千瓦,而运算能力却远不及今天智能手机的CPU,尽管如此,它已经比当时的继电器计算机快一千倍。而随着晶体管、集成电路的出现,计算机技术以惊人的速度发展着,到今天各种计算机设备随处可见,甚至我们很多人每天的生活和工作都已经离不开计算机。 数字计算机发明之前,电子计算机都是模拟计算机。模拟计算机通过内部电子器件的电压、电流大小等来表示一个数字或物理量,进行处理。这种计算机处理问题的精度差,而且结构复杂,也很容易受外界干扰。于是后来人们发明了数字计算机。数字计算机把外界的各种信息转换成数字,然后对数字进行运算,最终得到一个确定的结果。我们人类使用的数字一般为十进制,这是因为我们有十个手指。但是由于很多电子器件都只有两种确定的状态,比如开关的开和关,灯的亮和灭,于是数字计算机使用的是二进制的数字,通过控制器件的开和关来表示数字“1”和“0”,实现各种功能。由于它没有模拟计算机的那些缺陷,发展十分迅速,成为今天计算机的主流。 在计算机发展的同时,另一种大家相对陌生的东西也在悄悄发展着。在1971年,全球第一个计算机微处理器4004由美国Intel公司推出的同时,一种称之为单片机的技术也逐渐发展并得到广泛应用。单片机全称单片微型计算机,又称为微型控制器,英文名MCU(Micro Control Unit),可以理解为精简版的计算机。单片机相当于将计算机中的各个主要部件,CPU、存储器、IO口、中断系统等封装在一个集成电路芯片中。初学者或许对这些名词很陌生,但是不需要担心,关于他们分别是什么,后面会给大家介绍。 为什么要发明单片机呢?这个很好理解。俗话说,杀鸡焉用牛刀。生活中有很多事情不很复杂,并不需要计算机那么庞大的机器来处理,于是我们只需要用精简版的计算机——即单片机来完成任务就好了。 比起大家熟悉的计算机,单片机的配置可就差多了,简直是低的难以想象。我们常用的笔记本电脑CPU处理速度可以达到2GHz以上,还是双核四核甚至更高级,但是拿一款常见的单片机(STC89C52RC,我们即将以这款单片机开始来进行学习)来对比,它的最高处理速度只有几十MHz(其中1GHz = 1000MHz);笔记本电脑硬盘动辄几百GB乃至几TB,而单片机中相当于硬盘的ROM只有几到几十KB(1TB = 1024GB,1GB = 1024MB,1MB = 1024KB,1KB = 1024B);主流笔记本的内存普遍都有几个GB,单片机中相当于内存的RAM只有可怜的几十字节(即单位B)。但是大家千万不要小瞧这么“低端”的单片机,只要给它写进程序,足以控制一台我们经常看到的所谓“智能洗衣机”之类的电器。而且学习了单片机,也会让你对计算机有更深入的了解。

    时间:2018-04-25 关键词: 单片机

发布文章