电子系统设计-基于STM8抢答倒计时器.docx_第1页
电子系统设计-基于STM8抢答倒计时器.docx_第2页
电子系统设计-基于STM8抢答倒计时器.docx_第3页
电子系统设计-基于STM8抢答倒计时器.docx_第4页
电子系统设计-基于STM8抢答倒计时器.docx_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

电子系统设计课程论文题 目 基于STM8抢答倒计时器 学生姓名: 学 号: 专 业:电子信息工程 学 院:机械与电子工程学院 二 0 一 七 年 五 月 二十三 日目录1. 设计任务31.1. 功能简介31.2. 详细要求31.3. 实际设计功能偏差32. 方案论证42.1. 设计方案简介42.2. 设计思路42.3. 器件选型42.4. 设计特点52.5. 技术关键点52.5.1. 多按键输入的分辨能力52.5.2. 多数码管显示是否卡顿63. 设计细节73.1. 系统结构73.2. 主循环状态机73.3. 多任务时间戳控制73.4. 按键输入83.4.1. 按键中断触发83.4.2. 3*3按键阵列扫描83.5. 数码管输出83.5.1. 三位七段式共阴数码管83.5.2. 刷新显示83.5.3. 十秒显示闪烁83.6. 功能切换与保存93.7. 完整代码93.7.1. stm8s_it.c93.7.2. main.c94. 实物演示205. 总结体会236. 参考文献231. 设计任务1.1. 功能简介设计一个电路系统,该电路系统功能为8选手抢答锁定、倒计时回答问题的功能。即8名选手在听到节目主持人“抢答”口令的时候,最快地按下各自的抢答按键,电路系统自动识别并锁定最早按下抢答键的选手编号,并显示出来,同时开始倒计时,倒计时为两位十进制显示。1.2. 详细要求l 可同时供8名选手参加比赛,编号分别为1,2,3,4,5,6,,8各用一个抢答按钮,按钮的编号与选手的编号相对应。l 节目主持人设置一个控制按钮K,控制系统复位,使编号显示数码管灯灭并表示抢答开始。 l 抢答开始后,若有选手按抢答按钮,其编号立即被锁存,且在LED数码管上显示出选手编号,并封锁输入电路,禁止其他选手抢答,获得优先抢答资格的选手的编号一直保持到主持人将系统复位为止。 l 要求具有回答限时功能,回答时间分为30秒和1分钟两种,回答过程中有倒计时显示,答题时间剩余10秒时有报警(指示灯亮)提示。1.3. 实际设计功能偏差将第四点详细要求“答题时间剩余10秒时有报警(指示灯亮)提示”改成:答题时间剩余10秒时,数码管显示编号开始闪烁,闪烁频率为2Hz。2. 方案论证2.1. 设计方案简介采用STM8单片机作为主控芯片,3*3的阵列键盘扫描输入,3个七位并行总线扫描输出到数码管刷新显示2.2. 设计思路根据设计任务可知,该电路系统主要分为三个部分:输入按键、数字电路、数码管显示。倘若采用纯数字逻辑电路需要使用大量74或CD系列逻辑芯片,并且接线复杂,整个电路体积庞大,能耗高,设计复杂。秉着尽量减少设计周期的设计原则,同时兼顾体积、能耗比、性价比等多方面,采用廉价的STM8单片机来代替复杂的数字逻辑电路,可以大幅度降低电路结构复杂度,降低硬件设计的难度。计算机编程更容易实现复杂多样化的功能,同时具备未来功能改造和升级的能力,STM8是ST意法半导体的自主开发的八位单片机,其性能与价格都优越于51单片机系列,该单片机具有通用输入输出引脚,支持开漏输出、推挽输出和上拉输入,推挽输出模式单引脚可以输出或输入的电流达到20mA,意味着不需要外接三极管就可以直接驱动数码管或者LED灯等,上拉输入意味着不需要外接上拉电阻,极大的减少外围电路,内部集成十六位定时器,支持外部中断等等功能,完全能够实现电子抢答器的功能。2.3. 器件选型本次设计具体使用的STM8型号为STM8S103F3P6,该单片机拥有16个IO引脚可供使用,引脚配置上,分配6个引脚为3*3阵列键盘的行列输入输出引脚,x0x2位上拉输入,y0y2为推挽输出,7个引脚为并行总线数码管ag的阳极,推挽输出,3个引脚分别为各个数码管的共阴端com,开漏输出 并不是所有IO都支持推挽输出,STM8S103F3Px型号的PB4与PB5引脚只支持开漏输出,数码管共阴COM口只需要提供下拉能力即可,故此可以配置为开漏输出代替推挽输出。16个引脚全部用上没有浪费,由于没有多于的引脚无法单独控制指示灯亮的功能,因此改成数码管显示编号闪烁(见1.3设计功能偏差),如图1所示。 图1数码管选用3个2*5引脚八段数码管,小数点不使用,单个导通压降在1.75V左右,工作电压为3.3V,控制电流在1mA左右,故此选用1K欧姆限流电阻串联。按键使用6*6,4引脚方形微动按键。2.4. 设计特点l 电路结构简单,一个单片机,9个按键,3个数码管,7个电阻即可完成工作。l 价格低廉,STM8单片机价格在可以控制在1元左右,最低低至0.5元,相比纯数字电路要用到大量逻辑芯片具有很强性价比。l 功耗低,外围电路少,耗电器件少。l 功能可软升级,多样化,无需修改硬件电路。l 技术安全性高,不易被抄袭2.5. 技术关键点2.5.1. 多按键输入的分辨能力STM8单片机的主频为16MHz,在按键输入的功能中,采用的方式为:先外部中断触发,后按键扫描。两种方式互相配合实现尽可能快的阵列键盘输入判断。详细工作方式如下:配置x0x2引脚为上拉输入,下降沿触发的外部中断引脚,y0y2初始状态全部输出为低。当有按键按下的时候,按键所在的x引脚就会被下拉,产生中断信号,单片机进入指定中断函数进行按键判断。在中断函数中,首先读取并保存x0x2输入状态,然后再判断是哪个行输入引脚触发了中断(或哪些),为低即为被按下。确定了xi行,之后,依次将y0y2引脚输出高电平,并每次读取xn行的状态,如果xi行状态变为了高,说明对应的y j列和xi行所对应的按键,即为当前触发中断,或者说最早按下的按键。据上所述,即可判断最早按下的按键。当然扫描的过程是需要时间的,在这段时间内按下的按键仍然无法判断向后。根据逻辑分析仪分析得到,扫描的过程不超过50us。并且由于采用的是中断触发的方式,比传统的循环扫描更快更具有实时性,因此按键在时间上的分辨率可以达到50us。同时由于采用的是先保存行后扫描列的方式,同x不同y的分辨率为50us(需要扫描),而不同x的分辨率低至5us(在扫描之前就已经确认)。这时间分辨率远大于人的反应时间100ms以上的要求,故此可以认为能够实现要求。2.5.2. 多数码管显示是否卡顿数码管总共有3个,采用的是并行共用ag总线,独立COM脚的接线方式,通过轮流输出com0com2为低,轮流显示三个数码管。在总的时间上,每个数码管显示的时间为1/3,相当于亮度降为常亮的1/3,这个亮度配合1K欧电阻表现较为合适,人眼能明显看到数字的点亮。在刷新速度上,但总的刷新速度超过60FPS的时候,人眼就会感觉流畅,分辨不出闪烁。因此,设定单个数码管显示时间间隔为5ms,那么总的刷新率为因此不会有卡顿现象。3. 设计细节3.1. 系统结构3.2. 主循环状态机分为四个状态,准备状态、锁定倒计时状态、十秒提示倒计时状态、倒计时结束准备状态:该状态编号数码管不显示,倒计时数码管显示30或者60。锁定倒计时状态:数码管显示锁定编号,倒计时状态,每一秒钟数字减少1.十秒提示倒计时状态:倒计时到了最后十秒,开启闪烁显示,倒计时继续倒计时结束:该状态编号停止闪烁,倒计时归零不动。除准备状态外,按下复位键都可回归到准备状态准备状态时,按下复位键,倒计时在30、60秒之间切换。3.3. 多任务时间戳控制使用定时器TIM1,配置该定时器周期为1ms,中断程序中增加全局变量time的值。程序任何地方都允许读取但不允许修改该值,读取该值便可得到当前运行的时间戳,在主循环中,通过读取当前时间戳和设定时间点大小,即可实现非阻塞式延时或者说是软件定时的功能。3.4. 按键输入3.4.1. 按键中断触发当按键中断被允许的时候,有按键按下,即可触发中断。中断处理中,首先记录时间戳,并关闭按键中断,关闭中断的目的是为了防止按键抖动多次触发中断的软件消抖方式。记录时间戳,用于等待一定时间之后,重新打开按键中断。其次进行行锁存,列扫描,判断出第一个按下的按键和其他“同时”按下的按键。并保存到结构体对应变量中。3.4.2. 3*3按键阵列扫描阵列按键,无法通过读取单独的引脚就能准确判断按下的按键,必须先确定按键所在行,然后依次改变列的输出,再次读取对应行,来判断准确的按键位置。3.5. 数码管输出3.5.1. 三位七段式共阴数码管电路连接上,将三个数码管ag相同的连接在一起,串联1K欧电阻连接到对应IO口,输出高为点亮,输出低为熄灭。COM口下拉为选中,浮空为不选中。3.5.2. 刷新显示设定指定时间间隔,切换com口和输出的ag的编码在切换数码管的时候,先将所有com浮空,然后根据要显示的数值,查表的到对应的ag七位编码,然后将这七位编码控制到IO口上进行输出。最后拉拉低下一个com口,进行电亮显示。依次循环,即可实现刷新显示。外部函数只需要修改“显存”的值即可改变刷新显示的内容,与刷新方式无关、时间要求无关。3.5.3. 十秒显示闪烁在不关闭5ms刷新功能、1000ms倒计时功能,利用时间戳,再加上每250ms切换,编号显示数码管的输出,当显示编号的时候,改为不显示;当为不显示的时候改为编号输出。切换周期为4Hz,则对应闪烁频率为2Hz。据此可实现闪烁警告3.6. 功能切换与保存STM8内置了EEPROM存储器,可以实现断电保存,当切换倒计时时间30/60的时候,同时保存当前倒计时值到EEPROM中,下次开机的时候将会自动读取保存的倒计时值。3.7. 完整代码3.7.1. stm8s_it.cextern void key_IT( void );extern volatile uint32_t get_time, time_key;INTERRUPT_HANDLER(EXTI_PORTD_IRQHandler, 6)time_key = get_time + 20;key_IT();INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11)+get_time;TIM1_ClearITPendingBit(TIM1_IT_UPDATE);3.7.2. main.c#include stm8s.h#include stm8s_conf.h#include stm8s_exti.h#include stm8s_it.h#define CONT_NUM60/设置倒计时时间#define KEY_ARRAY_X_MAX3#define KEY_ARRAY_Y_MAX3#define DLED_COM_MAX3#define KEY_X_IO_PIN_ALL(GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6)#define _ledx_off( _dled_x_ )GPIO_WriteLow( dled.io (uint8_t)(_dled_x_) .port, (GPIO_Pin_TypeDef)( dled.io (uint8_t)(_dled_x_) .pin )#define _ledx_on( _dled_x_ )GPIO_WriteHigh( dled.io (uint8_t)(_dled_x_) .port, (GPIO_Pin_TypeDef)( dled.io (uint8_t)(_dled_x_) .pin )#define _comx_l( _com_x_ )GPIO_WriteLow( (uint8_t)(_com_x_) .port, (GPIO_Pin_TypeDef)( (uint8_t)(_com_x_) .pin )#define _comx_h( _com_x_ )GPIO_WriteHigh( (uint8_t)(_com_x_) .port, (GPIO_Pin_TypeDef)( (uint8_t)(_com_x_) .pin )#define _disable_key_it()( (key_array.key_x0.port)-CR2 &= KEY_X_IO_PIN_ALL)#define _enable_key_it()( (key_array.key_x0.port)-CR2 |= KEY_X_IO_PIN_ALL)typedef struct IO_structGPIO_TypeDef * port;uint8_tpin;IO_TypeDef;typedef struct DLED_structIO_TypeDefio7;uint8_tcom_num;IO_TypeDef*com;DLED_TypeDef;#defineKEY_NONE 0#defineKEY_ONE 1#define KEY_WAIT0xffutypedef struct KEY_ARRAY_structuint8_tx_n, y_n;/行数和列数。行上的引脚用于输入,列用于输出IO_TypeDef*key_x;IO_TypeDef*key_y;_IO uint16_tkey_all;/位存储方式,最低位为按键1,8为复位键uint8_tkey_num;_IO uint8_tkey_state;KEY_ARRAY_TypeDef;typedef enumQDQ_READY = 0,QDQ_REPLAY = 1,QDQ_WARN = 2,QDQ_OUT = 3QDQ_state_TypeDef;typedef struct QDQ_structuint8_tdisplay DLED_COM_MAX ;/提供给DLED刷新函数,刷新显示的值,低位对应最左边一个数码管uint8_tdisplay_com;/当前显示的数码管号,QDQ_state_TypeDefstate;uint8_tcont, lock_n;QDQ_TypeDef;const IO_TypeDefdled_com DLED_COM_MAX = /数码管,三个共阴脚定义GPIOC, GPIO_PIN_3,GPIOB,GPIO_PIN_4,GPIOB,GPIO_PIN_5;const DLED_TypeDef dled = GPIOD,GPIO_PIN_2,/对应数码管agGPIOD,GPIO_PIN_3,GPIOC,GPIO_PIN_6,GPIOC,GPIO_PIN_4,GPIOC,GPIO_PIN_5,GPIOC,GPIO_PIN_7,GPIOD,GPIO_PIN_1,3,dled_com;const uint8_t DLED_tab11 = 0x3Fu,/00x06u,/10x5Bu,/20x4Fu,0x66u,0x6Du,0x7Du,0x07u,0x7Fu,0x6Fu,0x00u/10为不显示;const IO_TypeDefkey_x_io KEY_ARRAY_X_MAX = GPIOD,GPIO_PIN_4,GPIOD,GPIO_PIN_5,GPIOD,GPIO_PIN_6,;const IO_TypeDefkey_y_io KEY_ARRAY_Y_MAX = GPIOA,GPIO_PIN_3,GPIOA,GPIO_PIN_2,GPIOA,GPIO_PIN_1,;KEY_ARRAY_TypeDefkey_array = KEY_ARRAY_X_MAX,KEY_ARRAY_Y_MAX,key_x_io,key_y_io,0;QDQ_TypeDefqdq = 10, 10, 10, 0, QDQ_READY;uint32_t time_s, time_ref, time_key, time_warn;volatile uint32_t get_time = 0;void key_IT( void )static uint8_t i,j, c, tmp;if(key_array.key_state != KEY_NONE)return;_disable_key_it();/关闭中断,交由主线程决定什么时候再次开启按键阵列的中断,可以实现软件防抖c = ( (GPIO_ReadInputData( key_array.key_x 0 .port ) & KEY_X_IO_PIN_ALL;/将所有PD口的输入值同时保存下来,并按位取反(因为低有效)(只适用于行输入引脚都为同一组的情况for( i = 0; i key_array.x_n; +i)if( c & key_array.key_x i .pin )/如果对应的行输入被拉低for( j = 0; j key_array.y_n; +j)/再逐次改变Y列,输出高,再次读取行,如果行值变高,说明,对应YX的按键为按下按键GPIO_WriteHigh( key_array.key_y j .port, (GPIO_Pin_TypeDef)( key_array.key_y j .pin );if( (GPIO_ReadInputData( key_array.key_x 0 .port) & (uint8_t)( key_array.key_x i .pin )tmp = (key_array.y_n) * i + j;if( 1 = +(key_array.key_state)key_array.key_num = tmp + 1;key_array.key_all |= (uint16_t)(0x0001u tmp);GPIO_WriteLow( key_array.key_y j .port, (GPIO_Pin_TypeDef)( key_array.key_y j .pin );if(key_array.key_state = KEY_NONE)/如果检测一圈发现,没有检测到任何按键。检测无效,重新开启中断_enable_key_it();/*void key_check( void )/非中断扫描键盘static uint8_t i,j;/*for( j = 0; j key_array.y_n; +j)/Y列,先全部输出高GPIO_WriteHigh( key_array.key_y j .port, (GPIO_Pin_TypeDef)( key_array.key_y j .pin );*/*for( j = 0; j 0; +i);/短暂延时for( i = 0; i = _num )qdq.display_com = 0;c = DLED_tab qdq.display qdq.display_com ;/取要显示的数值对应的编码for( i = 0; i = 0x01u, +i )/从A到G依次输出if( c & 0x01u )_ledx_on( i );else_ledx_off( i );_comx_l( qdq.display_com );void time_down( void )if( get_time time_s )if( 0 = (qdq.display2) )/为0的时候。要借位if( 0 = (qdq.display1) )/十位为0,qdq.state = QDQ_OUT;qdq.display0 = qdq.lock_n;return;qdq.display2 = 9;-(qdq.display1);else-(qdq.display2);if( qdq.state = QDQ_REPLAY & (qdq.display2 = 0) & (qdq.display1 = 1 ) )/倒计时为10的时候,进入WARN状态qdq.state = QDQ_WARN;time_warn = time_s + 250;time_s += 1000;/不以get_time为准,而以原有值为基准,增加精度void rstkey_check( void )if( KEY_NONE != key_array.key_state & KEY_WAIT != key_array.key_state )if( ( 0x0100u & (key_array.key_all) ) | 10 = key_array.key_num )key_array.key_all = 0;qdq.state = QDQ_READY;qdq.display1 = qdq.cont / 10;qdq.display2 = qdq.cont % 10;qdq.display0 = 10;key_array.key_state = KEY_WAIT;void main(void)uint8_t i; /* Initialize I/Os in Output Mode */CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);get_time = 0;disableInterrupts();TIM1_TimeBaseInit(16-1, TIM1_COUNTERMODE_UP, 1000-1, 0x00);/启用定时器,设定为1ms为周期,自动增加get_time全局变量的值TIM1_ITConfig(TIM1_IT_UPDATE, ENABLE);TIM1_ClearFlag(TIM1_FLAG_UPDATE);GPIO_Init( GPIOD, (GPIO_Pin_TypeDef)(GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 ), GPIO_MODE_IN_PU_IT );/配置为上拉中断模式EXTI_DeInit();EXTI_SetTLISensitivity(EXTI_TLISENSITIVITY_RISE_ONLY);/下降沿触发中断EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOD, EXTI_SENSITIVITY_FALL_ONLY);enableInterrupts();TIM1_Cmd(ENABLE);/* 引脚模式定义及初始化 */GPIO_Init( GPIOA, (GPIO_Pin_TypeDef)(GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1), GPIO_MODE_OUT_PP_LOW_FAST );GPIO_Init( GPIOD, (GPIO_Pin_TypeDef)(GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1), GPIO_MODE_OUT_PP_LOW_FAST );GPIO_Init( GPIOC, (GPIO_Pin_TypeDef)(GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7), GPIO_MODE_OUT_PP_LOW_FAST );GPIO_Init( GPIOB, (GPIO_Pin_TypeDef)(GPIO_PIN_4 | GPIO_PIN_5), GPIO_MODE_OUT_OD_HIZ_FAST );time_ref = 0;time_s = get_time + 1000;FLASH_Unlock(FLASH_MEMTYPE_DATA);/解锁EEPROMif( SET != FLASH_GetFlagStatus(FLASH_FLAG_DUL)return;qdq.cont = FLASH_ReadByte(0x4086);uint32_ttmp = 0;tmp |= FLASH_ReadByte(0x4040);tmp |= FLASH_ReadByte(0x4041) 8;tmp |= FLASH_ReadByte(0x4042) 16;tmp |= FLASH_ReadByte(0x4043) 8) & 0x000000ffu);FLASH_ProgramByte(0x4042, (uint8_t)(tmp 16) & 0x000000ffu);FLASH_ProgramByte(0x4043, (uint8_t)(tmp 24) & 0x000000ffu);qdq.display0 = 10;qdq.display1 = qdq.cont / 10;qdq.display2 = qdq.cont % 10;qdq.state = QDQ_READY;key_array.key_state = KEY_NONE; while (1) if( key_array.key_state = KEY_WAIT & (get_time time_key)/延时开启按键中断if( KEY_X_IO_PIN_ALL & (GPIO_ReadInputData( key_array.key_x 0 .port ) )/检测按键是否仍然按住,是则增加延时继续等待松开time_key += 5;elsekey_array.key_state = KEY_NONE;key_array.key_all = 0;_enable_key_it();if(get_time time_ref)/定时刷新数码管dled_ref();time_ref += 5;/当切换间隔为5ms以内的时候,三个数码管的刷新率为66HZ,符合人眼if( qdq.state != QDQ_READY ) & KEY_WAIT != key_array.key_state & KEY_NONE != key_array.key_state & (key_array.key_all & 0x0100u )key_array.key_all = 0;qdq.state = QDQ_READY;qdq.display1 = qdq.cont / 10;qdq.display2 = qdq.cont % 10;qdq.display0 = 10;key_array.key_state = KEY_WAIT;switch( qdq.state )case QDQ_READY:if( KEY_NONE != key_array.key_state & KEY_WAIT != key_array.key_state )/按键不为空的时候,说明有按键按下if( !( key_array.key_all & 0x0100u ) & (key_array.key_num != 10) )/按下的按键不为 复位键时qdq.display0 = qdq.l

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论