本作品使用基于Cortex -M3
的LM3S811
单片机通过开关型霍尔传感器A04E检测车轮的转数,利用SSI(同步串行通信)模块向两片级联的74HC595发送16位的数据来驱动六位数码管,其中高八位用于片选,低八位用于段选。通过一个按钮来切换显示速度和里程。1系统方案
1.1 电源由于
LM3S811的工作电压是3.3V,所以直接采用两节5号干电池供电。1.2 显示由于速度与里程的范围:
0~40.01和0~700.1,只需5位即可显示。所以用2片3位的数码管吗组成1片6位的,其中第一位分别显示U和
L代表速度和里程。1.2 检测采用外部中断当单片机检测到下降沿时,计数值加一。每隔一秒计算一次速度。
2系统理论分析与计算2.1 数码管显示 将
6个数码管的段选并联,由U1控制;U2的低6位用作片选码。数据帧的大小为16位,其中0~7位为段选码,第8~13用于片选码LM3S811在上电时,所有GPIO引脚默认为输入,软件设计根据应用要求配置GPIO引脚。在使用
SSI时,需通过对RCGC1寄存器中的SSI位置位使能SSI外设时钟。配置SSI为主机模式,协议模式为Freescale SPI单次传输模式。为了切换显示速度和里程,分别用定时器
1和定时器2定时中断,不断刷新数码管。外加一个按钮,当键按下时初始化定时器1,显示里程;否则只初始化定时器2,显示速度。2.2 计算速度与里程在车轮一周上均匀放置
6个磁钢,假设车轮半径0.5m,则车轮转一周为π m
。每两个磁钢之间的距离位
π/6 m
。磁钢检测采用外部中断,每中断一次计数器加1。再用定时器0定时中断,每隔一秒计算一次速度,v=counter*π/6 m/s
转换成V=v*3.6 km/h,里程
mile则一直累加。 3电路与程序设计3.1 数码管显示电路
file:///C:UsersADMINI~1AppDataLocalTempksohtmlwps82DB.tmp.png file:///C:UsersADMINI~1AppDataLocalTempksohtmlwpsB7B3.tmp.png3.2 程序的设计
3.2.2程序
程序采用KEIL MDK 使用C语言编写,由主程序、外中断0服务程序,T0中断服务程序、T1中断服务程序等模块组成。4. 最后效果5.
附录:源程序#include"hw_memmap.h"#include"hw_types.h"#include"ssi.h"#include"hw_ints.h"#include"sysctl.h"#include"gpio.h"#include"timer.h"#include"interrupt.h"#define uint unsigned int#define uchar unsigned char#define ulong unsigned longuchar disp_buf[6];uchar disp_buf1[6];uchar disp_tab[13]={0x003f,0x0006,0x005b,0x004f,0x0066,0x006d,0x007d,0x0007,0x007f,0x006f,0x003e,0x0038,0x0080};ulong TheSysClock=6000000;float temp;ulong num,counter,speed,mile;uchar v_qian,v_bai,v_shi,v_ge,l_qian,l_bai,l_shi,l_ge;ulong ulClock,ulBitRate;//
定义磁块检测 #define PULSE_PERIPH SYSCTL_PERIPH_GPIOD#define PULSE_PORT GPIO_PORTD_BASE#define PULSE_PIN GPIO_PIN_4extern jtagwait(void);//SSI
初始化void ssiInit(void){ ulBitRate=TheSysClock/10; SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);//
使能SSI模块 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);//
使能SSI所在引脚 GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2);//(SSI0CLK_PORT, SSI0CLK_PIN);//
将相关GPIO设置为SSI功能 GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_3);//PA3 SSI0FSS_PORT GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_4);//PA4 SSI0RX_PORT GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5);//PA5 SSI0TX_PORT SSIConfig(SSI0_BASE, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, ulBitRate, 16);//SSI
配置:基址,协议格式,主/从模式,位速率,数据宽度 SSIEnable(SSI0_BASE);//
使能SSI收发}//
定时器2A初始化void timer2AInit(){ ulClock = TheSysClock/150;// (60 * 8);//
扫描速度在60Hz以上时,人眼才不会明显感到闪烁 SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); //
使能Timer模块 TimerConfigure(TIMER2_BASE,TIMER_CFG_32_BIT_PER);//
配置为32位周期定时器 TimerPrescaleSet(TIMER2_BASE,TIMER_BOTH,100);//
配置分频值 TimerLoadSet(TIMER2_BASE, TIMER_A, ulClock); //
设置Timer初值 TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);//
使能Timer超时中断 IntEnable(INT_TIMER2A); //
使能Timer中断 IntMasterEnable(); //
使能处理器中断 TimerEnable(TIMER2_BASE,TIMER_A);//
使能TIMER0A }//
定时器1初始化void timer1AInit(){ ulClock = TheSysClock /150;// (60 * 8);//
扫描速度在60Hz以上时,人眼才不会明显感到闪烁 SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); //
使能Timer模块 TimerConfigure(TIMER1_BASE,TIMER_CFG_32_BIT_PER);//
配置为32位周期定时器 TimerPrescaleSet(TIMER1_BASE,TIMER_BOTH,100);//
配置分频值 TimerLoadSet(TIMER1_BASE, TIMER_A, ulClock); //
设置Timer初值 TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);//
使能Timer超时中断 IntEnable(INT_TIMER1A); //
使能Timer中断 IntMasterEnable(); //
使能处理器中断 TimerEnable(TIMER1_BASE,TIMER_A);//
使能TIMER0A }//
定时器0初始化void timer0AInit(){ ulClock = TheSysClock/10 ;// (60 * 8);//
扫描速度在60Hz以上时,人眼才不会明显感到闪烁 SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //
使能Timer模块 TimerConfigure(TIMER0_BASE,TIMER_CFG_32_BIT_PER);//
配置为32位周期定时器 TimerPrescaleSet(TIMER0_BASE,TIMER_BOTH,100);//
配置分频值 TimerLoadSet(TIMER0_BASE, TIMER_A, ulClock); //
设置Timer初值 TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);//
使能Timer超时中断 IntEnable(INT_TIMER0A); //
使能Timer中断 IntMasterEnable(); //
使能处理器中断 TimerEnable(TIMER0_BASE,TIMER_A);//
使能TIMER0A }//
系统时钟初始化void systeminit(){ SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN|SYSCTL_XTAL_6MHZ); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC|PULSE_PERIPH); GPIOPinTypeGPIOInput(PULSE_PORT,PULSE_PIN);//
设置磁块检测PD4为输入 GPIOIntTypeSet(PULSE_PORT, PULSE_PIN,GPIO_FALLING_EDGE);//GPIO_LOW_LEVEL); GPIOPinIntEnable(PULSE_PORT, PULSE_PIN); IntEnable(INT_GPIOD);}void GPIO_D_IntHandler(void){ulong ulstatus;ulstatus=GPIOPinIntStatus(PULSE_PORT,true);//
读取中断状态GPIOPinIntClear(PULSE_PORT,ulstatus);if(ulstatus&PULSE_PIN){counter++;}} int main(){ jtagwait();//
等待jtag systeminit(); timer0AInit(); ssiInit(); while(1) { if(num==10)//
每一秒计算一次 { {temp=counter*31.41/6; speed=temp*36; //
把m/s换成km/h temp=temp*0.01; mile=mile+temp; } num=0; counter=0; } if (GPIOPinRead(GPIO_PORTC_BASE, GPIO_PIN_4) == 0x00)//
若按下KEY,则显示里程,否则显示速度 {timer2AInit();} else {timer1AInit();}} }void Timer2ATimeoutIntHandler(void) //
中断服务{ TimerIntClear(TIMER2_BASE,TIMER_TIMA_TIMEOUT);//
清楚中断标志位 v_qian=speed/1000;v_bai=speed/100%10;v_shi=speed/10%10;v_ge=speed%10; disp_buf[0]=10;disp_buf[1]=v_qian;disp_buf[2]=v_bai;disp_buf[3]=12;disp_buf[4]=v_shi;disp_buf[5]=v_ge; SSIDataPut(SSI_BASE,0xfe00|(disp_tab[disp_buf[0]])); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); SSIDataPut(SSI_BASE,0xfd00|disp_tab[disp_buf[1]]); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); SSIDataPut(SSI_BASE,0xfb00|disp_tab[disp_buf[2]]); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); SSIDataPut(SSI_BASE,0xf700|disp_tab[disp_buf[3]]); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); SSIDataPut(SSI_BASE,0xef00|disp_tab[disp_buf[4]]); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); SSIDataPut(SSI_BASE,0xdf00|disp_tab[disp_buf[5]]); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); }void Timer1ATimeoutIntHandler(void){ TimerIntClear(TIMER1_BASE,TIMER_TIMA_TIMEOUT); l_qian=mile/1000;l_bai=mile/100%10;l_shi=mile/10%10;l_ge=mile%10;disp_buf1[0]=11;disp_buf1[1]=l_qian;disp_buf1[2]=l_bai;disp_buf1[3]=l_shi;disp_buf1[4]=12;disp_buf1[5]=l_ge; SSIDataPut(SSI_BASE,0xfe00|(disp_tab[disp_buf1[0]])); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); SSIDataPut(SSI_BASE,0xfd00|disp_tab[disp_buf1[1]]); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); SSIDataPut(SSI_BASE,0xfb00|disp_tab[disp_buf1[2]]); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); SSIDataPut(SSI_BASE,0xf700|disp_tab[disp_buf1[3]]); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); SSIDataPut(SSI_BASE,0xef00|disp_tab[disp_buf1[4]]); SysCtlDelay(1* (SysCtlClockGet( )/ 3000)); SSIDataPut(SSI_BASE,0xdf00|disp_tab[disp_buf1[5]]); SysCtlDelay(1* (SysCtlClockGet( )/ 3000));}void Timer0ATimeoutIntHandler(void){TimerIntClear(TIMER0_BASE,TIMER_TIMA_TIMEOUT);//
清楚中断标志位 num++;}
下面图片就是实物拍的
一周热门 更多>