【中科昊芯Start_DSC28027勇士开发板试用体验】计时器

描述

本文来源电子发烧友社区,作者:xiaopeng, 帖子地址:https://bbs.elecfans.com/jishu_2290500_1_1.html

计时器演示

一、说明

勇士开发板上有一个四位共阴数码管,于是想着能用它来显示点什么,想了一下,也没什么可以显示的,只好用它来做个计时器,因为只有四位,也不可能显示很复杂的内容。

四位数码管如果同时显示分钟和秒中,正好可以用前两位显示分钟,后两位显示秒中,那么可以最大显示99分钟59秒。想好了就开始干。

二、方案设计

1、查看原理图

开发板试用

从原理图可以看出,开发板使用了一颗I2C接口的数码管驱动芯片TM1650,驱动芯片与DSP之间只需要两个IO口就可以实现数码管的控制,还是非常方便的。
另外,该芯片通过读的方式能够检测外部的按键。

2、TM1650介绍

TM1650是一款国产4位共阴数码管驱动芯片,它还带有矩阵按键扫码功能。它的基本参数如下:

  • 工作电压:3~5V
  • 数码管驱动模式:8段x4位共阴数码管
  • 矩阵按键驱动模式:7x4矩阵按键,不支持组合键
  • 通信接口:类IIC,使用了IIC相同的时序,但没有完全遵守IIC的协议,不带从机地址

引脚定义

SCL:串行通信时钟线

SDA:串行通信数据线

做数码管驱动使用时

  • DIGx:数码管的位选引脚,灌电流驱动,最大可吸收150mA电流

  • A~DP:数码管的段驱动引脚,拉电流驱动,最大可输出25mA电流
    开发板试用

    通信协议

TM1650使用的是类IIC接口,只是不带从机地址机制。所以总线上的基本信号也包含起始信号,ACK应答,结束信号,同时字节数据发送时,也是按照标准IIC的MSB First顺序。

发送命令设置数码管显示工作参数

通信格式:起始信号,模式命令(1字节),显示命令(1字节),结束信号

这个指令用于设置数码管显示的相关参数。例如亮度,7段或者8段显示,显示的开关。模式命令固定为0x48,而显示命令则满足以下格式:
开发板试用

3、设计思路

计时:因为勇士027系列dsp没有硬件RTC模块,所以只能使用硬件定时器来实现。使用cputimer0来设置1ms的周期中断,在中断里面进行计数,计数到1s后进行更新数码管显示。

暂停功能:利用按键s101来实现计数的暂停与继续。

亮度调节功能:利用按键s102来实现数码管亮度的调节

计数复位功能:利用按键s103来实现计数值的复位,从零开始计时

三、代码编写

main.c

#include "dsc_config.h"
#include 
#include "IQmathLib.h"
#include "sci.h"
#include "TM1650_IIC.h"
#include 

extern void InitKEY(void);
extern void InitLED(void);
void test(void);
Uint16 sec_rtc = 0;
Uint16 min_rtc = 0;
char keyReg = 0;

extern Uint32 msec_cnt;//用于计秒
extern volatile Uint8 msec_cnt_on;//0-on,1-off
int main(void)
{
	uint16_t cnt = 0;

	/*初始化系统控制:PLL,WatchDog,使能外设时钟*/
	InitSysCtrl();
	/*初始化内存控制寄存器,使能内存流水线模式*/
	InitFlash();

	/*初始化串口通信的GPIO口*/
	/*GPIO28: SCIRXDA*/
	/*GPIO29: SCITXDA*/
	InitSciGpio();

	/*关闭中断*/
	DINT;

	/*将PIE控制寄存器初始化为默认状态,该状态禁止所有PIE中断并清除所有标志*/
	InitPieCtrl();
	/*禁止CPU中断并清除所有中断标志*/
	IER = 0x0000;
	IFR = 0x0000;
	/*初始化PIE向量表,为PIE向量表中的所有中断向量配置对应向量的入口地址*/
	InitPieVectTable();
	/*SCI寄存器配置*/
	Scia_Config(9600);
	/*定时器0初始化*/
	Timer0_init();

	/*初始化IIC总线的Gpio*/
	InitI2C_Gpio();
	/*IIC初始化*/
	I2CA_Init();
	/*软件复位IIC从设备*/
	softResetIIC_BUS();
	//printf("\r\nTM1650 init...");//标准C的printf输出测试,串口调试助手设置波特率128000bps,ASCII格式显示

	/*BIT6到BIT4为亮度调节,BIT0是  1 开启/0关闭*/
	LigntVal = 0x11;
	/*1级亮度,开启显示*/
	TM1650_Send(CMD_SEG, LigntVal);
	/*DIG0-DIG3均显示0*/
	TM1650_Send(DIG0, SEG7Table[0]);
	TM1650_Send(DIG1, SEG7Table[0]);
	TM1650_Send(DIG2, SEG7Table[0]);
	TM1650_Send(DIG3, SEG7Table[0]);

	/*使能外部中断和CPU中断*/
	EINT;

	/*初始化KEY、LED*/
	InitKEY();
	InitLED();

	/*通过SCI发送字符串*/
	Scia_Print("Hello haawking!\r\n");
	while(1)
	{
		if((CpuTimer0.InterruptCount % 250) == 0)
		{
			/*TM1650获取扫描按键S101 S102 S103,控制数码管数字显示及亮度调节*/
			TM1650_Read(CMD_KEY, &keyVal);

			/*S101按下时,开始/暂停计时*/
			if(keyVal == 0x44)
			{
				msec_cnt_on ^= 0x01;
				uart_printf("msec_cnt_on = %d\r\n",msec_cnt_on);
			}
			/*S102按下时,改变数码管显示亮度*/
			if(keyVal == 0x4c)  //
			{
				/*高四位为亮度调节,最后1位是开启、关闭显示*/
				LigntVal = (LigntVal + 0x20) & 0x7F;

				/*1级亮度,开启显示*/
				TM1650_Send(CMD_SEG, LigntVal);
				uart_printf("LigntVal = %d\r\n",LigntVal);
			}

			/*按下S103时*/
			if(keyVal == 0x54)
			{
				msec_cnt = 0;
				sec_rtc = 0;
				min_rtc = 0;
				keyReg = 0;

				/*DIG0-DIG3清零*/
				TM1650_Send(DIG0,SEG7Table[0]);
				TM1650_Send(DIG1, SEG7Table[0]);
				TM1650_Send(DIG2, SEG7Table[0]);
				TM1650_Send(DIG3, SEG7Table[0]);

				/*D400翻转*/
				GpioDataRegs.GPATOGGLE.bit.GPIO7 = 1;
				uart_printf("cnt reset\r\n");
			}
		}

		/*间隔为1000ms*/
		if(msec_cnt >= 1000)
		{
			/*定时器0中断次数清零*/
			msec_cnt = 0;

			/*D401翻转*/
			GpioDataRegs.GPATOGGLE.bit.GPIO6 = 1;

			/*Tmp累加,从0-999循环*/
			sec_rtc++;
			if(sec_rtc >= 60)
			{
				sec_rtc = 0;
				min_rtc++;
				if(min_rtc >= 100)
				{
					min_rtc = 99;
					sec_rtc = 59;
				}

			}

			//分钟十位
			TM1650_Send(DIG0,SEG7Table[min_rtc / 10]);
			/*分钟各位*/
			TM1650_Send(DIG1, SEG7Table[min_rtc % 10]);

			/*秒十位*/
			TM1650_Send(DIG2, SEG7Table[sec_rtc / 10]);
			/*秒个位*/
			TM1650_Send(DIG3, SEG7Table[sec_rtc % 10]);
		}
	}

	return 0;
}

// ----------------------------------------------------------------------------

timer.c

/******************************************************************
 文 档 名:     epwm.c
 D S P:       DSC28027
 使 用 库:
 作     用:
 说     明:      提供timer接口初始化配置
 ---------------------------- 使用说明 ----------------------------
 功能描述:


 版 本:V0.0.3
 时 间:2022年1月19日
 作 者:
 @ mail:support@mail.haawking.com
 ******************************************************************/
#include "dsc_config.h"
#include "TM1650_IIC.h"
#include "timer.h"

timer0 timer0Base;
volatile uint32_t Tick;
Uint32 msec_cnt = 0;//用于计秒
volatile Uint8 msec_cnt_on = 0;//0-on,1-off
/******************************************************************
 *函数名:Timer0_init
 *参 数:无
 *返回值:无
 *作 用:初始化Timer
 ******************************************************************/
void Timer0_init()
{
	/*初始化Cpu定时器*/
	InitCpuTimers();

	/*开启模块中断使能,位于 Timer->RegsAddr->TCR.bit.TIE = 1;
	 120MHz,1000us ,即为 1ms中断周期*/
	ConfigCpuTimer(&CpuTimer0, 120, 1000);
	/* 使能中断*/
	CpuTimer0Regs.TCR.bit.TIE = 1;
	/* 开始计时*/
	CpuTimer0Regs.TCR.bit.TSS = 0;

	/*重映射中断服务函数*/
	EALLOW;
	PieVectTable.TINT0 = &cpu_timer0_isr;
	EDIS;
	/*连接CPU中断Y*/
	IER |= M_INT1;
	/*连接Y中断里的第几位*/
	PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
}
/******************************************************************
 *函数名:INTERRUPT void cpu_timer0_isr(void)
 *参 数:无
 *返回值:无
 *作 用:CPU 定时器0 中断服务函数
 ******************************************************************/

INTERRUPT void cpu_timer0_isr(void)
{
#if 0
	timer0Base.msCounter++;
	timer0Base.Mark_Para.Status_Bits.OnemsdFlag = 1;

	Tick++;
	/*中断响应*/
	EALLOW;
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
	EDIS;

#endif

	/*定时器0中断次数累计*/
	CpuTimer0.InterruptCount++;
	if(msec_cnt_on == 0)
	{
		msec_cnt++;
	}

	/*检测IIC模块状态为空闲还是写入*/
	char i;

	for(i = 0; i < IIC_NODE_NUM; i++)
	{
		PtrMsg[i]->IIC_TimerOUT = (PtrMsg[i]->MasterStatus == IIC_IDLE) ? 0 : (PtrMsg[i]->IIC_TimerOUT + 1);
	}

	/*通知可以接收第一组中断的所有中断*/
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分