和记娱乐


网站导航

联系我们

和记娱乐

联系人: 

电 话:021-64057486

公司网址:http://www.happy123456789.com

   址:成都市松江区漕河泾松江新兴产业园区研展路丰产支路55号B座803室

邮编:201165


通信知识

您的当前位置: 和记娱乐主页 > 通信知识 >

单片机学习中的常见问题

发布日期:2019-08-26 07:19 来源:和记h88 发布人:和记娱乐 点击:

  在单片机学习中,我们常常遇到这样那样的零星问题,这里我将我遇到的问题总结如下,都是个人见解,如果不对,万望指出。(持续更新中)

  7.下载软件用的什么版本,旧版本可能需要设置最低、最特率,并且还会出现很多奇怪的现象,比如第一次烧写用一个波特率,第二次就不行了,但是有时候却一直可以(个人经验)。新版本不用设置,并且不用等待软件提醒上电才可以上电,点击下载后,直接重新上电即可,尽量使用新版 ;

  8.如果使用的是CH340/CH341或者PL2302,检测RXD/TXD是否连接反了。(注意PL2302,驱动,新版的驱动只支持正版芯片,这个一定要注意,很多人会沿用老版本驱动,不用PL2302)

  10.一部分人修改上一次工程代码,然后直接编译,下载无效果。可能是新的代码编译有错(编译有三个按钮,请注意区别差异),导致目标文件未生成,hex文件未更新,所以下载的还是上一次的程序。这里要注意。

  11.STC-ISP软件选择hex文件后,要勾“每次下载前都重新装置文件”,这样有三大好处:(1)免去每次编译都重新手动装在hex文件(2)避免因忘记手动重新装载hex文件,而导致下载的hex文件还是上一次的hex文件,代码下载后现象和上一次一样,误以为还是程序问题(3)方便快速调试代码。

  13.芯片“锁死”。STC-ISP软件设置问题,上一次下载程序的时候,在STC-ISP可能勾选了“下次冷启动时,P1.0 / P1.1为0/0才可以下载程序” , 这种情况,试着将此两个IO拉低,下载程序试试看。

  最近看到群里面有很多人为了学习单片机,下载了STC-ISP,然后又下载了串口软件、单片机小精灵、定时器计算神器之类的,可谓五花八门,但是实际我们并不需要那么多的软件。

  大家注意到STC-ISP软件已经附带了很多功能了,学会使用这些功能可以让我们事半功倍。另外,STC手册上有C语言和汇编语言程序,值得参考。下面在分析几款常用软件给大家:

  Proteus7.5 仿真:点击打开链接 (文件中包含我的破解过程,目前我的系统为W8.1暂时未发现使用问题)

  51类单片机下载程序时必须冷启动,这是大家都知道的。昨天,一个学生告诉我他是用的普中科技开发板,他用普中科技的下载软件去下载程序,发现不是很好用。我告诉他STC-ISP下载软件非常好用,他说STC-ISP软件必须经过手动重启开关完成下载,而普中科技的开发板,可以完成全自动下载,只需点击“下载”按钮即可,无需手动重启开关,并且普中科技技术支持告诉他,只能使用他们的软件才能够完成全自动下载(我对此只能呵呵)。本人也是采用普中科技开发板,普中科技的自动下载功能确实存在,但是我使用过发现并不是很好用,而且需要结合它的开发板硬件才行。这里介绍一下我使用过的两种“全自动”下载(可能方法还有很多,需要广大网友的补充)

  (1)硬件法:利用STC自动下载器,点击下载后,模块会自动重新上电,完成下载任务,需要淘宝购买,约9~13元。

  (2)软件法:利用串口结合IAP功能,点击下载,模块自动完成下载,无需手动重启。(版本古老的芯片无此功能)此方法可参考我的笔记:stc单片机“全自动下载”(程序版)

  在C语言方面,这是可以的(尽管这样不是很规范),但是在keil4中,却出现了问题,网上百度,说可能是有中文字符,但是我将程序删除后,编译没有错误,切换输入法,再次输入图片2的内容,出错,将int i=0 ; 剪切到第一行,错误消失。还有一个可能是软件出错(经过测试,排除可能性)。

  在单片机程序中,有时候会需要“死循环等待”,也就是等到某一条件我们才需要执行下面的操作。这里以温度传感器DS18B20为例,主机首先需要发送一个存在检测脉冲,如果DS18B20存在,则它会以60us至240us的电平来回应主机,这里就会需要一个“死循环等待”,我们必须等到DS18B20“回应完成”,这时候主机才能继续发送指令到DS18B20中去,这时候很多人会采用这样的方式:(首先假设sbit ds18b20_io_bit = P3^7 ;)

  这样的代码其实是有问题的,在未连接DS18B20或者接触不良时,DS18B20并不能回应主机,这样的代码就会有问题,尤其在大工程中,所以,为了安全,我通常的做法是:

  因为i一般都很小,所以这时候我一般将unsigned long 修改为unsigned char 类型,然后最后修改为这样

  注意这里的250不是随意写的,是经过测试的,经过测试,我读出的i值远小于250,我才这样做的,如果在其他类似的地方,打印出来i是其他较大的值,那就重新定义i的类型为unsigned int 或者unsigned long ,根据具体情况而定。

  的修改似乎意义不大,但是在大工程中,这样不会因为DS18B20的“不存在”而导致整个程序“死循环等待”。

  特殊功能寄存器的寻址方式只有直接寻址和位寻址。没有间接寻址方式。而指针却是间接寻址方式,不能通过指向特殊功能寄存器的指针来操作特殊功能寄存器。

  例:利用指向0x90的指针来操作P1口的LCD灯(高电平时LCD点亮)(P1口的地址是0x90,但是属于特殊功能寄存器区)

  在某些芯片操作时,会有一些引脚或者寄存器或地址的数据被用来表明当前芯片处于的状态为忙碌状态或者空闲状态,如果忙碌,单片机需要用轮询的方式等待直到芯片空闲下来才继续发送指令或数据。这里以1602液晶屏为例:

  一个朋友用ST89C52操作1602液晶屏,操作成功,后来换了芯片STC12C5A60S2,同样的程序,显示出来的却是“乱码”,后来经过测试,程序部门似乎没有问题,于是,我在LCD1602的“写命令”函数和“写数据”函数中

  加入了延时(只是为了快速测试),下载后,两个芯片都运行正常。其实对于LCD1602,一般都不需要“判忙”,它运行时比较快的,但是如果将一个没有“判忙”的1602液晶屏模块封装起来,在调试一个大工程时,这时候

  因为换了芯片,导致整体效果错误,这就是增加了调试难度。比如在利用LCD1602学习使用时钟芯片DS1302时,如果显示乱码,这时候,因为你的LCD1602是实验的基础环节,肯定是你之前就已经封装好了的,这时候

  你肯定会怀疑DS1302环节操作出错了,这就增加了调试的难度和时间。所以,“判忙”函数必不可少。这里,又有一个技巧,就是防止程序“卡死”,含义与本文中的问题0002类似。

  打印出i的值为 “1”(基于芯片STC12C5A60S1,11.0592MHZ,其他型号的单品机可能打印出来的效果不同,甚至同样的型号单片机、同样的晶振、同样型号的1602 操作打印出来的值也是不一样的),又变化为:

  这样做才是安全的。(尤其在大系统中,不会因为1602的”不存在“导致整个系统的运行失败,经典案例如下)

  (在2015年2月7日,我帮助一个大四学生调试毕设时,也发现了同样的问题,此同学在1602液晶屏的写命令、写数据函数里面加入了判忙函数,判忙核心代码如下:

  ,最后因在系统设计时,暂时用了1602显示,后来为了做上位机,就用了串口通信代替1602, 拔掉了1602液晶屏,但是没有屏蔽掉主函数中关于1602的操作,导致了程序卡死在判忙函数中,因为如果没有硬件连接,通过数据口读取到的1602状态数据是0xff,然后0xff&0x80,这样得到的结果永远是1(除非再次插上液晶屏或者手动将数据最高bit对应的IO口拉低),导致程序卡死在这里,而且这些功能都是封装好的,所以就更加加大了难度,导致一周没有调试出来,后来,我给他指出两种方法(1)在主函数中屏蔽所有关于1602液晶屏的函数,实验后,系统运行正常(2)修改判忙函数,因为一劳永逸,试验后,运行正常,即使主函数中没有屏蔽1602相关函数,1602硬件暂时取下,也是可以成功运行的)

  另外,还有很多同用了延时的方法去操作,似乎大部分人都得到了满意的结果,那么,这里有出现了两个问题:(1)延时的结果有三种:延时太小、延时正好、延时太大,对于大家来说,延时正好、延时太大都是可以完成系统的设计的,但是,你又如何你的延时不会小呢?大部分人想,这非常简单,把延时设计的非常大就好了,那么,就引出了问题(2)延时太大,不利于系统整体设计,导致了效率太低 。 何去何从,大家可以想一想。

  有时候,在调试程序时,明明都是严格按照datasheet的说明和时序图编写的代码,就是没有效果,然后借鉴别人的代码,代码相同,但还是没有效果 。 这时候,先要怀疑硬件,如果硬件没有问题,有可能还会有一个原因,那就是单片机的问题(或者是keil软件的问题,这个不得而知了)。我之前遇到过编写一个代码,没有效果,最后把全部代码屏蔽掉,只在main函数中,点亮了LED,但还是失败了,后来,复制代码,重新新建工程,粘贴代码,就好了。(这里不是喷STC,其实STC在国内做的较好,但是总会有一些奇葩的时候),这里分享一下,仅个人经历。

  单片机程序测试调试似乎对于刚入门的同学有一定难度,但是入门之后我们快速调试程序呢?很多人写代码一气呵成,然后在main函数中调用10几个子函数,然后直接通过液晶屏或者其他的手段观察效果是正确,这样的方法对吗 ?以下是常用方法:

  1.借助于网上的视频或源代码,(对于32位的MCU尚可理解,但是51、PIC.MSP430单片机使用者如果入门后还是同样的方法,你就OUT了),但只适用于部分网上资料较多的芯片。

  2.借助"逻辑分析仪"仪器去分析(这种神器我也是通过网上资料介绍,有所了解,但是并没有使用过,不过好像非常好用的),通过逻辑分析仪可以分析我们的时序是否存在问题,但是个人感觉比较适用于菜鸟和破解单片机程序的高手,对于大多数用户,没有必须花钱购买

  3.利用程序本身去验证程序,编写一个函数,测试一个函数,操作简单,屡试不爽,这里以大家熟知的51类单片机STC12C5A60S2和数字温度传感器DS18B20为例(单总线协议通信)。

  下图为DS18B20的“复位”时序,因为每次操作都需要MCU发送一个复位信号,所以,“复位”函数相当重要。

  我们知道,当DS18B20存在时,红色部分的时间内,总线将会被DS15B20拉低,呈现低电平 ; 如果DS15B20不存在,则在单片机使用总线(蓝色)后,红色部分仍然是高电平。

  (1)正常连接DS18B20,结果如果是P1的第一个灯亮了(P1=0x01),则表示单片机可以检测到DS18B20的存在,说明函数可能对了(可以检测到DS18B20的存在);

  (2)拔掉DS18B20,结果如果是P1的第二个灯亮了(P1=0x02),则表示单片机未检测到DS18B20的存在,说明函数完全正确。(可以同时检测到DS18B20的存在和不存在)

  注意:只有当(1)(2)都正确后,才表示此“复位”函数编写正确了。然后继续进行下面的函数编写。

  同样的,对于很多芯片,我们使用51单片机驱动时,都会涉及到“读操作”和“写操作”,在编写读写函数时,通常严格按照时序编写“写”函数和“读”函数,然后向芯片的内部RAM写入一个数据(这个数据最好不是0xff,因为当芯片未连接时,单片机读出的数据就是0xff,这时候如果我们写0xff,然后读取,因为结果肯定是0xff,所以并不能证明我们的读写函数书写正确),然后读出该地址的数据,验证数据是否相同,如果相同,表明读写操作正确,但是这里同时需要注意一个问题:读/写操作周期为多少?即需要隔多长时间MCU才可以继续读/写此芯片,因为对于芯片,我们读写一次后,可能需要过一段时间才可以继续读写,如果没有注意这个问题,就可能导致:编写的代码好像没错,但是在后期我们连续对芯片进行读/写操作时,没有注意这个延时等待啊,就会出现很奇怪的问题(通常这种错致的结果是随机的),这时候反过来调试过程可能就繁琐了,如果连续操作间隔较长,安全的做法是:在每一次读/写操作后,都加一个延时,这样就肯定OK了。

  很多人现在都开始使用蓝口模块,利用手机蓝牙或者PC蓝牙进行控制单片机系统。但是很多人一上来就直接把蓝牙模块和单片机相连接,然后编写程序,效果实现不了,就不知该如何了。蓝牙模块很多都是结合了串口通信的,通常拿到模块,需要经过一下步骤(自己总结,可做参考):

  把你的开发板的单片机取下来,然后从开发板引出电源线VCC和GND,还有P30、P31接口,连接蓝牙模块的四个端口(注意RXD和TXD不要反接了)

  (2)通过PC的串口软件(比如STC-ISP软件自带的串口),设置好软件的波特率和通信数据格式,通过串口软件发送AT命令(通常购买时卖家提供了),看是否有返回数据,如果没有返回,有可能是P30、P31接口需要换过来,如果发送命令,有返回信息且不是乱码,表示蓝牙模块和PC可以串口通信了。

  (3)手机下载软件“蓝牙串口”,通过此软件连接蓝牙模块(蓝牙的名称和配对密码可通过 AT命令设置),然后给蓝牙模块供电,PC打开串口软件,手机发送任意字符到蓝牙模块,会发现PC串口软件接收到了信息,这表示蓝牙可以正常工作。

  先不连接蓝牙模块,编写程序,单片机接收到串口数据,做出相应动作,写好后下载,然后打开PC的串口软件,发送命令,检验现象是否正确,如果正确,开始第二步

  把蓝牙模块连接到单片机,手机蓝牙连接模块,手机发送命令,此时只要步骤现象经过反复验证没有问题,第二步肯定没问题。(如果第二步不对,那就返回去做第一步)

  (5)其他。如果需要用PC的蓝牙进行控制,还需要购买蓝牙适配器,也就是模块发送信息到电脑时,需要一个接收器。如果不是很必要,就用手机蓝牙软件就好了,省钱省事。

  (1)你只是想单纯的解码出来而已 :可以查看一下你用的遥控器类型,然后百度一下试试看 , 然后结合示波器观看。

  <2>不是很严格,但是很实用 : 先在网上看一个红外遥控器的协议,然后根据它的协议去解码,然后,查看解码的是否正确(通过原码和反码初步验证) , 然后把按下每一个按键,去记录下他的编码,然后下一设计要用到它的时候,你就把上次记录的编码,做一个数组,然后自己去定义每一个编码对应的功能即可。(因为实际上很多类型的编码,无非是引导码的时间不同,当然我们可以不关心引导码 ,还有就是0和1的定义不同,再或者就是先传输的是高位还是低位 , 就是以上三点不同---->个人理解,可能有所偏差,但是对于我们,我们可以不关心解码得到的是对的,还是不对的--->这里的“不对”是指是否和其真实的编码相同,而不是解码失败。我们只需要关注,接收到的信息是否和数组里面的一样,如果一样,就完成某种功能。 当然,这里有更加简单的方法,就是无需每次记录,用一个薄码开关,去选择学习模式和工作模式,这时候定义一个数组,然后先进入学习模式下,将接收到的信息放在数组中,然后进入工作模式,工作模式下只是对比此次接受的编码和数组当中的编码,如果相同,则完成一定的任务就可以了)

  现在在这里做统一解答 : (1)Proteus仿真和实物有差异,在Proteus中成功的代码不一定可以用于实物,反过来,实物上已经成功的代码也不一定可以用于Proteus。如果出现了一方成功,一方失败,那么很大的就是延时。(当然不排除其他可能性,但这个延时问题可能最大)

  (2)如果软件仿真和硬件实验,只有一方可以成功,而另一方失败。 那么表明你的逻辑上没有错误。参照第一条,稍做修改即可 。

  程序的严格性似乎总是被很多人遗忘,在编写程序时,一定要把隐患消灭掉,否则后患无穷。这里以1602液晶屏为例,希望可以作为一个切入点,但是要通过问题,看到问题本质,而不仅仅局限于1602液晶屏,思想更加重要。大家都知道1602液晶屏的数据口是8位数据口,但是实际上还有一种模式,就是4位数据口,实质上很简单,就是利用4位数据口传送数据,传送两次而已,其他无差别,但这不是这里讨论的关键。下面看一下网友的代码(只放关键部分):

  其中,我们之关心两句话,就是DataPort= Data; 和DataPort= Data<<4; 这两句话什么意思呢 ? 就是通过P0端口的高4个Bit,把数据传送两次,使用的是P04,P05,P06,P07。这里的实验网友成功了,他认为这个代码没有问题,但是这里的隐患确实非常明显的,如果不该掉,可能导致这样的情况发生:在1602的液晶屏4位数据口模式的实验中成功了,但是在一个复杂的系统设计中,却出现了很多意料之外的情况。实际上,问题较为突出,比如第一句DataPort= Data ; 从我们看出,对于1602而言,他只关心和他的4位数据口连接的 P04,P05,P06,P07的状态,但是的复制,却影响到了P00,P01,P02,P03,这里明显不行的,比如P00,P01,P02,P03连接了LED或者其他设备,这时候会影响到他们的运行。所以我的是,修改为:

  这里,希望新手可以通过这,看到问题的本质,将隐患在摇篮,否则简单的1602的4位数据口模式,会成为你调试复杂系统调试的噩梦。

  我们在使用液晶屏的时候,无论是1602/12864、NOKIA、J2004A还是其他的,常常遇到需要显示一个变量(尤其是小数),那么显示变量又有一些小小的技巧,这里把我的一些使用方法,给新手介绍一下,欢迎新人学习,更加欢迎高手拍砖(但不能总是拍,得让我知道为什么被拍)

  /*显示,百位这里我一直最高是百位,所以没有判断更加位,实际操作时,应该添加其他机制,使其更加智能*/

  发现液晶不仅显示了数据,而且有了四舍五入的果。实际上,这里为了实验效果,部分代码并没有做很好的处理,主要是为了凸显出重点,网友们可以在我的基础上不断修改,希望大家可以通过点,看到面,不要局限于这一个方式。

      和记娱乐,和记h88,h88平台官网