2018-09-13 20:18:38 qq_15156387 阅读数 239
  • 嵌入式软件开发

    课程主要讲解一些在开发中需要知道的常识,以及一些常见的开发平台,开发中应当注意的事项以及一些实战技巧,这些全部均来源于我的CSDN博客发表的内容。

    10126 人正在学习 去看看 杨源鑫
单片机开发过程中,使用集成开发工具(如Keil)在线调试的时候,点击调试按钮,会出现调试失败,检查软件设置没有发现问题。将板子使用的外部看门狗芯片MAX6369使用电烙铁拆除后,调试正常,查阅手册发现原因如下:
MAX6369使用外部引脚S2.S1.S0控制最长喂狗时间,![MAX6369引脚设置与复位时间](https://img-blog.csdn.net/20180913200734299?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzE1MTU2Mzg3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70),当设置的时间较短的时候,程序还未烧录进单片机,看门狗已经溢出达到复位条件,拉低单片机的复位引脚导致调试过程中单片机异常复位,致使调试失败。同样,如果在程序中设置断点,程序运行到断点处长时间暂停也会使得看门狗溢出导致异常复位。
本次板子使用C8051F410芯片、Keil开发工具、MAX6369看门狗芯片设置复位时间为1S,不能够正常使用在线调试功能。
综上,使用外部看门狗的时候,程序调试过程中最好不焊接看门狗芯片。正式使用的时候,为了能够正常对程序进行升级,看门狗时间不可以设置的过短,或者在板子上设计对应电路可以暂时屏蔽掉看门狗功能,升级之后再予以恢复。
2019-08-16 16:16:56 XLazyDog 阅读数 101
  • 嵌入式软件开发

    课程主要讲解一些在开发中需要知道的常识,以及一些常见的开发平台,开发中应当注意的事项以及一些实战技巧,这些全部均来源于我的CSDN博客发表的内容。

    10126 人正在学习 去看看 杨源鑫

 

借助蓝牙调试器我们可以很轻易地通过各种控件操作变量,现在要考虑的是如何让单片机获知这些变量?

首先确定单片机和蓝牙串口模块的连接方式:

需要注意的是蓝牙串口模块与单片机之间的连接,其TX、RX与单片机TX、RX是交叉的。如果你使用STM32单片机的USART1的话,则 蓝牙的TX 连接 单片机的PA10口, 蓝牙的RX连接单片机的PA9口。

连接方式

连接好蓝牙串口模块后,就开始写单片机程序了。由于我已经编写好了可以自由配置的单片机端的程序,所以你可以很方便地实现收发功能。代码在这

1.数据结构设置

下面是我编写好的名为valuepack的代码,其是在STM32F103单片机运行的,你也可以针对不同的平台进行修改,在使用此功能前,你首先需要在valuepack.h中配置通信结构。

在valuepack.h中配置参数

1.1接收缓冲区尺寸

缓冲区用来暂存从手机接收到的数据包,每次执行readValuePack时将这些暂存的数据包解析。缓冲区的尺寸默认为1024。

1.2发送数据包结构 

这里定义发送到手机的数据包的结构,即状态回传。在这里你可以像在蓝牙调试器上一样设置数据包中五种变量的数目。需要确保在此设置的五种类型变量的数目与手机的“接收数据包结构”的设置相同。否则手机端将无法解析该数据包。

1.3接收数据包结构 

这里定义从手机接收的数据包的结构,需要确保在此设置的五种类型变量的数目与手机的“发送数据包结构”的设置相同。

接下来就可以通过调用其函数实现数据收发了。

2.串口配置

 

 

3.接收数据包

3.1接收数据包结构体

创建接收数据包

首先创建一个接收数据包,该数据包中包含了五个数组,对应不同的数据类型。比如rxpack.bools[0]可以访问bool类型的第一个变量。

3.2读包

在手机不断发送数据到单片机时,单片机需要定时执行readValuePack。读包的频率最好高于手机发送数据包的频率。

4.发送数据包

4.1发送数据包结构体

创建一个发送数据包,该数据包中包含了五个数组,对应不同的数据类型。比如txpack.bools[0]可以访问bool类型的第一个变量。

4.2发包

单片机定时执行sendValuePack函数,并传入要发送的数据包。sendValuePack函数执行频率不可过高,太高容易导致堵塞。

至此已经整个单片机端的数据收发就完成了。函数总共就三个 init、read和send,使用起来非常简单。

单片机端的源代码

2019-08-01 20:52:00 diaobu5775 阅读数 109
  • 嵌入式软件开发

    课程主要讲解一些在开发中需要知道的常识,以及一些常见的开发平台,开发中应当注意的事项以及一些实战技巧,这些全部均来源于我的CSDN博客发表的内容。

    10126 人正在学习 去看看 杨源鑫

STC8单片机ADC采样注意事项

最近在做一个模块,使用宏晶公司的STC8单片机开发,模块主要使用了单片机的ADC采样功能,因为需要10个以上的通道,而且模块要经常震动,所以希望使用一种耐操一点的芯片, 于是我使用了STC8系列的单片机,有16路通道的ADC,采样精度是12位,可以比较好的满足我的要求。 一开始模块做的还不错,半年之后有一次要进行改进,在程序上我加大了单片机通道切换之间的时间,然而最后却出现了采样出错的现象。

因为我要轮询所有的ADC通道,出于设计方面,我采用了特别的采样顺序,采样出错的结果不知道是怎么回事,在改了程序之后便出现了问题, 我一直认为是程序的问题,搞到最后怀疑人生了,,感觉难道这又是STC的一个bug?

不过,最后我终于在网上找到了一个线索,并且尝试按照那个方法改了一下程序,ojbk了。 贴一下那个线索的原话:

如果输入信号内阻很大(超过1K就算大了,如果10K就很大了),ADC输入端对地接一个0.01~0.1uF的电容。
切换通道后,第一次转换值丢弃。

为什么会有这些要求?为什么外挂专门的ADC也一样的有这种要求?
对于没有输入缓冲的ADC(STC的ADC输入就是没有缓冲的),采样时ADC输入端通过一个电阻(r,通常是几K欧姆)给采样电容C充电(采样电容一般是10~30PF,STC的可以按30PF计算),假设信号源内阻为R0,则采样充电就是((R0+r)*C),采样时间t一般是很短的,比如STC最快时采样就是几个时钟,时间很短。

贴一下我的ADC采集函数(更改之前的):

/**
 * [ADCRead description]
 * @Author     叶鹏程
 * @DateTime   2019-08-01T20:24:46+0800
 * @discrption : ADC采样函数,
 *  
 * @param      n                        [要采样的通道]
 * @param      value_point              [采样值存放地址]
 */
void ADCRead(uint8_t n,unsigned int  xdata *value_point){
    unsigned int adc_value = 0;
    
    ADC_SET_CHANEL(n);  //设置当前待转换的ADC通道
    ADC_START_ENABLE();

    while(ADC_STATE()); //等待转换
    
    ADC_FLAG_CLEAR();  

    adc_value = (int)ADC_RES << 8;                               //读取ADC结果
    adc_value |= (int)ADC_RESL;
    adc_value = adc_value>>4;

    *value_point = adc_value;
}

这是按照线索,更改之后的:

/**
 * [ADCRead description]
 * @Author     叶鹏程
 * @DateTime   2019-08-01T20:24:46+0800
 * @discrption : ADC采样函数,
 *  
 * @param      n                        [要采样的通道]
 * @param      value_point              [采样值存放地址]
 */
void ADCRead(uint8_t n,unsigned int  xdata *value_point){
    unsigned int adc_value = 0;
    
    ADC_SET_CHANEL(n);  //设置当前待转换的ADC通道
    
    ADC_START_ENABLE();
    while(ADC_STATE()); //等待转换
    ADC_FLAG_CLEAR();  
    
    /* 这是清除了第一次转换的值,采用第二次采样,这样在切换通道时更加稳定*/
    ADC_START_ENABLE();
    while(ADC_STATE()); //等待转换
    ADC_FLAG_CLEAR();  

    adc_value = (int)ADC_RES << 8;                               //读取ADC结果
    adc_value |= (int)ADC_RESL;
    adc_value = adc_value>>4;

    *value_point = adc_value;
}

总结,这是ADC电路的问题, 以后一定要注意这些东西, 看来还是自己的知识没有学扎实。 加油!

posted on 2019-08-01 20:52 Gentleaves 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/Gentleaves/p/11285243.html

2019-09-13 16:22:29 u010755676 阅读数 22
  • 嵌入式软件开发

    课程主要讲解一些在开发中需要知道的常识,以及一些常见的开发平台,开发中应当注意的事项以及一些实战技巧,这些全部均来源于我的CSDN博客发表的内容。

    10126 人正在学习 去看看 杨源鑫

单片机里面有很多中断资源,例如外部中断、定时器中断、串口中断等,这些中断资源应当用于处理相应的紧急事件,而不是顺序执行的常规事件,所以在编写中断子程序的时候应当十分注意。

具体的事务处理语句不应放在中断函数里面,中断子程序中的语句应当简洁明了,不应当有太多的语句。假如你在编写中断子程序的时候像在main函数中那样写一大串处理具体事务的指令的话,会在此中断中占用太多的时间,假如当有其他低优先级的中断信号来临的时候也可能导致中断丢失,发生程序的逻辑错误。所以,在中断子程序中的指令语句应当做到最短。

中断子程序中的语句不应当使用延时函数,不使用whiledo-whiledo-until等有等待延时功能的指令。在中断子程序中使用while、do-while、do-until等指令也会导致单片机在执行过程中在该位置延时或者等待太长的时间,当其他中断信号来临的时候同样也可能导致中断丢失。

那么应该怎么做呢?

在编写中断子程序的时候,应当巧用全局状态变量,在中断子程序中只改变状态变量值,在main函数中while(1)程序段内部判断该状态变量的值,根据状态变量的值再分别执行对应的事务处理语句。这就像你接到一个电话要你办某事,你也不能在一直接着电话把这件事做完吧,你需要把事情记下来,挂了电话再安排时间处理。

举个例子,一个串口触摸屏需要根据触屏中按键来执行对应的操作,需要使用到串口中断。假设触屏在触摸按键1时会发送数据A,触摸到按键2时会发送数据B,那么我们可以定义一个全局状态变量command:

unsigned char command;

在串口中断子程序中,根据接收到的不同串口数据改变command的值:

void 串口1中断函数()

{

switch (收到的串口数据)

{case A:  //假如收到按键1的动作,command赋值x1

{command=x1;

break;

}

case B:  //假如收到按键2的动作,command赋值x2

{command=x2;

break;

}

default: break;

}

}

在上面这个串口1的中断子程序中,switch是一个条件选择指令,当串口收到数据A,那么给command赋值x1, 当串口收到数据B,那么给command赋值x2。当然,上面的程序段只是一个说明的示意,不能直接复制编译到单片机中运行,在实际工程中需要根据不同单片机程序的编写规则进行开发。

接着在main函数中根据command的值执行不同的事务处理语句:

main函数()

{

while(1)

{

Switch (command)

{case x1:   //假如收到按键1的动作,执行事务处理1的程序

{事务处理1;

break;

}

case x2:  //假如收到按键2的动作,执行事务处理2的程序

{事务处理2;

break;

}

       default: break;

}

}

}

按照这样的程序,单片机在接收到触屏发出的代表不同按键的串口数据时,在串口中断子程序中改变全局状态变量的值command,这个语句很少,执行时间也短。再到main函数中根据command的不同值分别执行非常耗时间的具体事务处理程序。这样的程序分配,将使单片机运行高效而且合理。

更多精彩,微信公众号:yonkotech

中秋快乐!

沙鸥  2019.9.13

2011-11-08 23:01:49 sailor_shuishou 阅读数 1330
  • 嵌入式软件开发

    课程主要讲解一些在开发中需要知道的常识,以及一些常见的开发平台,开发中应当注意的事项以及一些实战技巧,这些全部均来源于我的CSDN博客发表的内容。

    10126 人正在学习 去看看 杨源鑫

        单片机开发过程中,很多时候都需要用到中断,不管是内部的还是外部的,但是在使用中断的时候一定要注意到中断之后,其程序的运行状态。尤其是涉及时序的。

       1、时序操作

        比方说,程序中要对外部EEProm进行读写,例如24C02,这是典型的涉及时序问题程序,这个时候,大家可得注意,当你在对24C02进行读写的时候,就应该禁止中断,因为这个时候中断的发生会影响时序,进而产生读写错误,造成不可知的后果。

        2、定时器中断

        很多时候,我们会用到定时器中断,用来计时。我们知道要是我们把相关的计时程序写到中断服务程序中,会占用更多的时间,影响主程序执行,很多时候我们会选择把相关计数的程序放到主程序中执行。这个时候需要注意,要是主程序的执行时间大于中断程序中定义的计时变量,就会出现计时不准确的问题。

       比方说,定时器1ms中断一次,中断服务程序里面有个变量time计数一次,主程序中,对time进行检测,要是time大于等于10则启动另外一个计数变量,这个时候要是主程序循环的周期大于1ms就会计数不准确。

没有更多推荐了,返回首页