最近做了一个数显电压表,电路上支持交流或直流电压显示,软件上支持七种不同的满量程档位,可以自由切换,有小数点自动移位,无效零消隐,超量程指示等功能,修改外部元件就可以做成不同量程的交流或直流电压表,不会编程的朋友也可以DIY出各种不同量程的交流或直流电压表。
主要元件有STM8S003F3单片机一片,自带ADC,0.56寸三位共阴数码管一个,再就是阻容稳压什么的,电路也很简单,爱好者自制很方便。本贴的程序都能在此硬件上测试通过。下面是电路原理图:
自从去年开始学了单片机以后,发现单片机没有想象中那么难,所以想做一个教程和大家一起共同学习。我的编译环境是IAR的EWSTM8-2102,本贴代码都在此环境下测试通过,其它编译环境未测试过。仿真下载工具为十元左右的无壳ST-Link。开发成本在单片机中个人认为是最低的。
先来看一看今天的主角:STM8S003F3的原理图
它有十六个I/O(输入输出)引脚,厂家给这些I/O编了号,分别是:
PA1,PA2,PA3,
PB4,PB5,
PC3,PC4,PC5,PC6,PC7,
PD1,PD2,PD3,PD4,PD5,PD6,
这些端口被分成了四组,分别是:PA,PB,PC,PD。注意,我们在编写程序的时候要时刻清楚这些端口号(也就是PAx,PBx什么的),而某端口是单片机上的第几号引脚通常是不关心的(做硬件的时候才考虑)。还有一点,端口号后面的数字是从0开始的,也就是说单片机里面有PA0,PA1,PA2,PA3,PA4,PA5,PA6,PA7八个端口号,引出到外面的只有三个,那么就是说PA1是第二个端口,PA2是第三个,PA3是第四个,PB,PC,PD是同样的。
下面再来看一看数码管,这个数码管有三个8,加上小数点里面实际上有24个发光二极管,但是它却只用了11个引脚,分别被命名为A,B,C,D,E,F,G,DP,1,2,3,其中1,2,3分别对应的是从左到右三个数码管,A,B,C,D,E,F,G,DP则与数码管的七段和小数点对应。大家知道有三个小数点,只有一个引脚与之对应,三个8字每个都有ABCDEFG段,如果要显示数字1的话应该怎么样做呢?我们这里用到的是共阴数码管,B和C同时拉高就是数字1了,但是有可能三个数码管都会显示数字1,怎么办?1,2,3号引脚分别是三个数码管的共阴极,1号拉低而2和3拉高则会在左边显示1。1,2,3三个引脚同时拉低则三个数码管只能显示三个相同的数字,想要三个数码管显示不同的数字只能采用分时显示的办法,具体来说就是先1号拉低2,3拉高,ABCDEFG段产生一个数字会在左边数码管上显示,然后2拉低1,3拉高,控制ABCDEFG段产生一个数字会在中间显示,然后3拉低1,2拉高,控制ABCDEFG段产生一个数字会在右边显示,就这样不断的循环,如果循环的速度比较快,人眼的暂留特性会让我们感觉三个数码管是同时显示的。
要玩单片机,那么C语言知识是必须要学的,下面就从一个C语言空程序开始讲起吧。
/*程序开始了,这里是注释,从左边的斜杠星开始,
中间可以包含任意多行,
***********************直到右边的星斜杠为止*/
/*下面是主函数,从这里开始执行程序*/
void main(void)
{
//双斜杠后面是单行注释
//程序的初始化部分写在这里
while(1)//大循环,永远不停
{
//需要不停循环执行的任务
}
//程序永远不可能执行到这里
}
以上就是一个空的程序,所有的C语言程序都必须有这样的框架,上面用到了三个C语言关键字:void,main,while。关键字有特定的用途,不能用作用户的标识符。因为函数名是main,所以是主函数,用户所要完成的所有任务都在主函数里面执行,main前面的void指main函数的返回值类型是“无类型”,函数名后面的小括号中是函数的参数,这里没有参数,所以参数也是无类型。对于单片机来说,主函数是不能执行结束的,所以在主函数里面写了个死循环,其中while就是循环的关键字,while后面小括号中的数字代表循环条件,非0值代表循环不停。
下面再看一看与STM8S003F3有关的四个重要文档,(1)STM8S参考手册,这个有中文版,但是中文版可能会有小小的误差,最好还是以最新的英文版为准。(2)STM8S003F3_DataSheet英文版,可以参考STM8S103F3中文版。(3)头文件iostm8s003f3.h,个人认为这是一个非常重要的文件,一定要学会这个文件的用法。(4)IAR编译器的参考手册,只有E文版,我E文不好,至今还没有看过。
单片机的端口(引脚)在上电后会处于输入状态,想要正确的使用端口就必须在程序中配置成我们需要的状态。
以上是参考手册里的内容,对端口操作实际上就是对单片机内的寄存器赋值,DDR寄存器决定了端口的方向,比如说我们要让PD2端口变为输出应该怎么写呢?写“PD_DDR_DDR2=1;”就可以了,是不是很简单?PD_DDR寄存器总共有8个位,对应PD端口的8个引脚(STM8S003F3只引出了六个),PD_DDR_DDR2只是其中的一个位,直接对应PD2引脚的方向,那么“PD_DDR_DDR2”是从哪里来的呢?它可不是单片机里固有的,是从头文件iostm8s003f3.h里来的,打开这个头文件,我们可以找到如下字段:
/*----------------------------------------------------------
* Port D bit fields
*---------------------------------------------------------*/
#ifdef __IAR_SYSTEMS_ICC__
#define PD_ODR_ODR0 PD_ODR_bit.ODR0
#define PD_ODR_ODR1 PD_ODR_bit.ODR1
#define PD_ODR_ODR2 PD_ODR_bit.ODR2
#define PD_ODR_ODR3 PD_ODR_bit.ODR3
#define PD_ODR_ODR4 PD_ODR_bit.ODR4
#define PD_ODR_ODR5 PD_ODR_bit.ODR5
#define PD_ODR_ODR6 PD_ODR_bit.ODR6
#define PD_ODR_ODR7 PD_ODR_bit.ODR7
#define PD_IDR_IDR0 PD_IDR_bit.IDR0
#define PD_IDR_IDR1 PD_IDR_bit.IDR1
#define PD_IDR_IDR2 PD_IDR_bit.IDR2
#define PD_IDR_IDR3 PD_IDR_bit.IDR3
#define PD_IDR_IDR4 PD_IDR_bit.IDR4
#define PD_IDR_IDR5 PD_IDR_bit.IDR5
#define PD_IDR_IDR6 PD_IDR_bit.IDR6
#define PD_IDR_IDR7 PD_IDR_bit.IDR7
#define PD_DDR_DDR0 PD_DDR_bit.DDR0
#define PD_DDR_DDR1 PD_DDR_bit.DDR1
#define PD_DDR_DDR2 PD_DDR_bit.DDR2
#define PD_DDR_DDR3 PD_DDR_bit.DDR3
#define PD_DDR_DDR4 PD_DDR_bit.DDR4
#define PD_DDR_DDR5 PD_DDR_bit.DDR5
#define PD_DDR_DDR6 PD_DDR_bit.DDR6
#define PD_DDR_DDR7 PD_DDR_bit.DDR7
#define PD_CR1_C10 PD_CR1_bit.C10
#define PD_CR1_C11 PD_CR1_bit.C11
#define PD_CR1_C12 PD_CR1_bit.C12
#define PD_CR1_C13 PD_CR1_bit.C13
#define PD_CR1_C14 PD_CR1_bit.C14
#define PD_CR1_C15 PD_CR1_bit.C15
#define PD_CR1_C16 PD_CR1_bit.C16
#define PD_CR1_C17 PD_CR1_bit.C17
#define PD_CR2_C20 PD_CR2_bit.C20
#define PD_CR2_C21 PD_CR2_bit.C21
#define PD_CR2_C22 PD_CR2_bit.C22
#define PD_CR2_C23 PD_CR2_bit.C23
#define PD_CR2_C24 PD_CR2_bit.C24
#define PD_CR2_C25 PD_CR2_bit.C25
#define PD_CR2_C26 PD_CR2_bit.C26
#define PD_CR2_C27 PD_CR2_bit.C27
以上我们看到PD端口的五个寄存器ODR,IDR,DDR,CR1,CR2中的每一个位都做了宏定义,这样我们就可以直接操作每一个端口,而不会影响同组端口的其它位。默认安装时头文件的位置在C:Program FilesIAR SystemsEmbedded Workbench 7.3stm8inc,我们可以复制到其它位置随时查阅。
现在我们可以开始编程了,目标是在最右边的数码管上显示数字1,查询共阴数码管的原理图,要在右边显示数字1就要B和C拉高,同时3要拉低就可以了,查询电路原理图我们知道了如下对应关系:B=PD3,C=PD6,LED3=PD2。上电后单片机的端口默认为输入状态,编程时我们先要把端口配置成推挽输出状态,这就是端口初始化过程。
好了,一个最简单的完整程序就写完了,现在来看一看程序下载的方法,电路板上留有四线(含电源和地线)的SWIM接口,可以进行仿真或者下载程序,除了电源和地线,还有二根线是NRST和SWIM线,分别和仿真器上对应的线接好就可以下载了。
实际的程序一般都不是这样写的,我们应该改写一下:
#include
/*输出端口宏定义*/
#define b PD_ODR_ODR3
#define c PD_ODR_ODR6
#define LED1 PD_ODR_ODR2
/*端口初始化函数*/
void Port_init(void)
{
PD_DDR_DDR2=1;//PD2改输出状态
PD_CR1_C12 =1;//PD2输出模式改推挽
PD_DDR_DDR3=1;//PD3改输出状态
PD_CR1_C13 =1;//PD3输出模式改推挽
PD_DDR_DDR6=1;//PD6改输出状态
PD_CR1_C16 =1;//PD6输出模式改推挽
}
/*显示数字"1"函数*/
void Display_1(void)
{
b=1;//段码B拉高
c=1;//段码C拉高
}
/*主函数,程序从这里开始执行*/
void main(void)
{
Port_init();//调用端口初始化函数
LED1=0;//指定右边共阴数码管点亮
Display_1();//显示数字"1"
while(1);//程序停在这里死循环
}
程序表面看起来好象变长变复杂了一点,其实不是的,看问题应该看重点,重点是主函数变得简洁一些了。通过宏定义和函数调用使主函数里边只有具体的任务,硬件特征消失了,程序模块化了,一个函数就是一个小模块,一般函数和主函数在形式上是一样的,只是主函数能调用一般函数,反之则不能。一般函数可以互相调用,还可以调用自身(递归)。端口宏定义就是接口模块。以后要是硬件改了而主程序不变的话就不用到主函数里来改了(这样也很容易出错),直接改接口模块就可以了。通过对比,我们也可以发现函数没有想象中的那么神密,实际上就是一组完成某种功能的语句封装起来了,并且给它起了一个形象化的名字,然后主函数叫到谁的名字(函数调用),谁(具体的函数)就来完成自己的任务。所谓宏定义更简单,就是简单的替代,通过上面两段程序的对比,大家可以体会一下宏定义是如何实现替代的
上一篇:STM8控制LCD12864液晶屏实验
下一篇:STM8S103串口通信初始化设置
推荐阅读
史海拾趣
DLP创新设计公司,一家专注于DLP技术应用的企业,通过精准的市场定位和灵活的市场策略,成功在电子行业中脱颖而出。公司深入了解消费者需求,针对不同市场推出差异化产品。同时,DLP创新积极寻求合作伙伴,通过渠道拓展和品牌建设,逐渐提高了市场占有率。其独特的商业模式和敏锐的市场洞察力,使DLP创新在激烈的市场竞争中保持了稳健的发展。
进入安卓时代,HTC再次展现了其敏锐的市场洞察力和强大的技术实力。2008年,HTC联合电信运营商T-Mobile推出了世界上第一款安卓手机T-Mobile G1,这款手机的成功标志着HTC正式进入了安卓阵营。随后,HTC推出了多款备受好评的安卓手机,如HTC Hero(G3)等,进一步巩固了其在智能手机市场的地位。与谷歌和安卓的合作,为HTC带来了前所未有的发展机遇。
除了自主研发外,eMemory还积极寻求与外部合作伙伴的联合研发。在2016年,eMemory与马来西亚的半导体晶圆代工厂Silterra联合宣布,基于Silterra 0.18微米CMOS制程技术的一次性可编程(OTP)存储器已经通过了验证。这一合作不仅证明了eMemory技术的先进性和可靠性,还为双方带来了新的市场机遇。
随着国内市场的逐渐饱和,Advanced Electronic Packaging公司开始将目光投向海外市场。公司积极参与国际电子展会和技术交流活动,展示其先进的封装技术和优质产品。同时,公司还加大了对海外市场的宣传力度,通过线上线下相结合的方式提升品牌知名度和影响力。在不懈的努力下,公司的产品和服务逐渐赢得了国际市场的认可和青睐,海外市场份额逐年攀升。
随着公司技术的不断进步,Advanced Electronic Packaging公司开始寻求与行业内知名厂商的合作机会。通过与一家全球领先的电子产品制造商达成战略合作,公司成功将其先进的封装技术应用于对方的高端产品线中。这一合作不仅提升了合作双方的产品竞争力,还为Advanced Electronic Packaging公司带来了可观的利润回报。此后,公司陆续与多家知名企业建立了合作关系,进一步巩固了其在电子封装领域的市场地位。
1.<<微波射频技术培训套装>> 本套装是台湾某教授给台湾知名电子企业员工培训讲课视频,授课的企业包括:明基电通、迅利电子、宇通全球等。 由于是给企业员工培训、且授课老师自己也有着多年的工程实践经验,所以视频讲课内容尽量摒弃繁琐 ...… 查看全部问答∨ |
|
以前C51中这样定义的:uint code Parameter[5]={ 1660, 1040, 300, 100, 50}现在在IAR中定义不行啊。… 查看全部问答∨ |
|
DLP这是我第一次听说的一个词语,课程讲解首先从原理开始说,让我们先对DLP有初步认识.DLP(DigitalLight Procession)数字光学处理, 这种技术要先把影像信号经过数字处理,然后再把光投影出来。知道这个后我就知道我们投影仪都是这个原理.他的核心部分 ...… 查看全部问答∨ |
|
MSP430FR5969是一款功耗极低的单片机,拿到评估板不难发现其有一个1mF的大电容,能使其断开电源后可以依靠电容供电工作一会。 1.接下来刷了一下OutOfBox开箱程序,这个代码包含:GPIO,ADC,中断,低功耗模式,UART通信,板载超级电容电压检测,FRA ...… 查看全部问答∨ |
本帖最后由 lianyiwei11 于 2014-11-14 12:39 编辑 1. 概述 LY2003系列 IC,内置高精度电压检测电路和延迟电路,是用于单节锂离子/锂聚合物可 再充电电池的保护 IC。 本 IC 适合于对 1 节锂离子/锂聚合物可再充电电池的过充电、过放电和过电流 ...… 查看全部问答∨ |