打印
[应用相关]

单片机学习中的常见问题

[复制链接]
手机看帖
扫描二维码
随时随地手机跟帖
41
zljiu| | 2021-12-11 09:18 | 只看该作者 回帖奖励 |倒序浏览
都是新手应该注意的地方

使用特权

评论回复
42
coshi| | 2021-12-11 09:19 | 只看该作者
还有就是要先检查裸板有没有问题

使用特权

评论回复
43
drer| | 2021-12-11 09:20 | 只看该作者
都是非常细节且容易忽略的地方

使用特权

评论回复
44
工程师犹饿死|  楼主 | 2022-2-21 22:57 | 只看该作者
只有当(1)(2)都正确后,才表示此“复位”函数编写正确了。然后继续进行下面的函数编写。

使用特权

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


使用特权

评论回复
46
工程师犹饿死|  楼主 | 2022-2-21 23:04 | 只看该作者
问题0010:蓝牙串口模块使用的正确步骤
  很多人现在都开始使用蓝口模块,利用手机蓝牙或者PC蓝牙进行控制单片机系统。但是很多人一上来就直接把蓝牙模块和单片机相连接,然后编写程序,效果实现不了,就不知该如何了。蓝牙模块很多都是结合了串口通信的,通常拿到模块,需要经过一下步骤(自己总结,可做参考):

(1)首先,需要蓝牙模块和PC的硬件连接,这里有两种方法:
        <a>把你的开发板的单片机取下来,然后从开发板引出电源线VCC和GND,还有P30、P31接口,连接蓝牙模块的四个端口(注意RXD和TXD不要反接了)

        <b>如果你有USB-TTL模块,可以直接连接蓝牙模块,无需单片机开发板转接过去。

使用特权

评论回复
47
工程师犹饿死|  楼主 | 2022-2-21 23:06 | 只看该作者
(2)通过PC的串口软件(比如STC-ISP软件自带的串口),设置好软件的波特率和通信数据格式,通过串口软件发送AT命令(通常购买时卖家提供了),看是否有返回数据,如果没有返回,有可能是P30、P31接口需要换过来,如果发送命令,有返回信息且不是乱码,表示蓝牙模块和PC可以串口通信了。

使用特权

评论回复
48
工程师犹饿死|  楼主 | 2022-2-21 23:07 | 只看该作者
(3)手机下载软件“蓝牙串口”,通过此软件连接蓝牙模块(蓝牙的名称和配对密码可通过 AT命令设置),然后给蓝牙模块供电,PC打开串口软件,手机发送任意字符到蓝牙模块,会发现PC串口软件接收到了信息,这表示蓝牙可以正常工作。

使用特权

评论回复
49
工程师犹饿死|  楼主 | 2022-2-21 23:07 | 只看该作者
(4)编写单片机程序,此时需要分为两步:
<a>先不连接蓝牙模块,编写程序,单片机接收到串口数据,做出相应动作,写好后下载,然后打开PC的串口软件,发送命令,检验现象是否正确,如果正确,开始第二步
<b>把蓝牙模块连接到单片机,手机蓝牙连接模块,手机发送命令,此时只要步骤<a>现象经过反复验证没有问题,第二步肯定没问题。(如果第二步不对,那就返回去做第一步)

使用特权

评论回复
50
工程师犹饿死|  楼主 | 2022-2-21 23:10 | 只看该作者
(5)其他。如果需要用PC的蓝牙进行控制,还需要购买蓝牙适配器,也就是模块发送信息到电脑时,需要一个接收器。如果不是很必要,就用手机蓝牙软件就好了,省钱省事。

使用特权

评论回复
51
工程师犹饿死|  楼主 | 2022-2-21 23:14 | 只看该作者
问题0011:不知道遥控器的编码协议,如何解码

不同的遥控器,其协议也不同.

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


(2)你想解码出来后,用到其他设计上去 :这里有两种方法
<a>较为严格 : 就是参考(1)的思路去实验,但是花时太多。

使用特权

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

使用特权

评论回复
53
工程师犹饿死|  楼主 | 2022-2-21 23:17 | 只看该作者
问题0012:Proteus仿真的那点事
越来越多的人,问我以下问题

(1)为什么我的程序在Proteus中可以运行,但在实物上却运行失败。
(2)为什么我的程序在实物上可以运行,但是Proteus中却运行失败。


    现在在这里做统一解答 : (1)Proteus仿真和实物有差异,在Proteus中成功的代码不一定可以用于实物,反过来,实物上已经成功的代码也不一定可以用于Proteus。如果出现了一方成功,一方失败,那么很大的就是延时。(当然不排除其他可能性,但这个延时问题可能最大)
   
    (2)如果软件仿真和硬件实验,只有一方可以成功,而另一方失败。 那么表明你的逻辑上没有错误。参照第一条,稍做修改即可 。

使用特权

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

#define  DataPort  P0
  void LCD_Write_Data(unsigned char Data)
{
//while(LCD_Check_Busy()); //忙则等待
DelayMs(5);
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
  EN_SET;
DataPort= Data<<4;
_nop_();
EN_CLR;
}

使用特权

评论回复
55
工程师犹饿死|  楼主 | 2022-2-21 23:18 | 只看该作者
其中,我们之关心两句话,就是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或者其他设备,这时候会影响到他们的运行。

使用特权

评论回复
56
工程师犹饿死|  楼主 | 2022-2-21 23:22 | 只看该作者
所以我的建议是,修改为:
 
第一次传送:
DataPort &= 0x0f ;         /*P0高4位清零,准备传送数据*/
DataPort |= (temp & 0xf0) ;/*P0传送数据temp的高4位,P0的低4位不受影响*/

第二次传送:
DataPort &= 0x0f ;                 /*P0高4位清零,准备传送数据*/
DataPort |= ((temp & 0x0f)<<4) ;/*P0传送数据temp的低4位,P0的低4位不受影响*/

使用特权

评论回复
57
工程师犹饿死|  楼主 | 2022-2-21 23:23 | 只看该作者
这里,希望新手可以通过这表象,看到问题的本质,将隐患扼杀在摇篮,否则简单的1602的4位数据口模式,会成为你调试复杂系统调试的噩梦。

使用特权

评论回复
58
工程师犹饿死|  楼主 | 2022-2-21 23:25 | 只看该作者
问题0014:液晶如何显示小数并且小数自动四舍五入
液晶显示数据的小小技巧:(主要针对液晶显示浮点型数据)
    我们在使用液晶屏的时候,无论是1602/12864、NOKIA、J2004A还是其他的,常常遇到需要显示一个变量(尤其是小数),那么显示变量又有一些小小的技巧,这里把我的一些使用方法,给新手介绍一下,欢迎新人学习,更加欢迎高手拍砖

使用特权

评论回复
59
工程师犹饿死|  楼主 | 2022-2-21 23:28 | 只看该作者
   (1)首先,我们需要先做一些预备知识:如何进行四舍五入:
    float temp = 2.376 ;


我们需要保留两位小数,也就是2.38(四舍五入后的结果)
    在程序中,我们只需要一句话:temp = (unsigned int)((temp*100)+0.5) / 100 ;就完成了这个功能,得到的结果就是2.38(不信可以试试看额)

使用特权

评论回复
60
工程师犹饿死|  楼主 | 2022-2-21 23:29 | 只看该作者
(2)液晶如何显示小数
    使用以下代码:
#include <reg52.h>
#include <string.h>
#include "lcd1602.h"
void main(void)
{
    float a = 182.376 ;
        
    lcd1602Init();
    lcd1602WriteCommand(0X0C);
   
    /*显示原来的数字,非重点*/
    lcd1602AddressWriteByte(LCD1602_ROW0,0,((unsigned long)a)%1000/100+'0') ;
    lcd1602AddressWriteByte(LCD1602_ROW0,1,((unsigned long)a)%100/10+'0') ;
    lcd1602AddressWriteByte(LCD1602_ROW0,2,((unsigned long)a)%10+'0') ;
    lcd1602AddressWriteByte(LCD1602_ROW0,3,'.') ;
    lcd1602AddressWriteByte(LCD1602_ROW0,4,(unsigned long)(a*10)%10+'0') ;
    lcd1602AddressWriteByte(LCD1602_ROW0,5,(unsigned long )(a*100)%10+'0') ;
    lcd1602AddressWriteByte(LCD1602_ROW0,6,(unsigned long )(a*1000)%10+'0') ;
   
    lcd1602AddressWriteByte(LCD1602_ROW0,8,0x7e) ;
   
   
    /*重点部分*/
   
    /*显示,百位这里我一直最高是百位,所以没有判断更加位,实际操作时,应该添加其他机制,使其更加智能*/
    lcd1602AddressWriteByte(LCD1602_ROW0,10,((unsigned long<span style="font-family: Arial, Helvetica, sans-serif;">)a)%1000/100+'0') ;</span>
    /*显示十位*/
    lcd1602AddressWriteByte(LCD1602_ROW0,11,((unsigned long)a)%100/10+'0') ;
    /*显示各位*/
    lcd1602AddressWriteByte(LCD1602_ROW0,12,((unsigned long)a)%10+'0') ;
    /*显示小数点*/
    lcd1602AddressWriteByte(LCD1602_ROW0,13,'.') ;
    /*显示小数点后第一位*/
    lcd1602AddressWriteByte(LCD1602_ROW0,14,(unsigned long)(a*10)%10+'0') ;
    /*显示小数点后第二位,此时需要四舍五入计算*/
    lcd1602AddressWriteByte(LCD1602_ROW0,15,(unsigned long )(a*100+0.5)%10+'0') ;
   
    lcd1602AddressWriteString(LCD1602_ROW1,0,"QQ:279729201") ;
   
    while(1);
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则