一、說明
勇士開發(fā)板上有一個四位共陰數(shù)碼管,于是想著能用它來顯示點什么,想了一下,也沒什么可以顯示的,只好用它來做個計時器,因為只有四位,也不可能顯示很復雜的內容。
四位數(shù)碼管如果同時顯示分鐘和秒中,正好可以用前兩位顯示分鐘,后兩位顯示秒中,那么可以最大顯示99分鐘59秒。想好了就開始干。
二、方案設計
1、查看原理圖
從原理圖可以看出,開發(fā)板使用了一顆I2C接口的數(shù)碼管驅動芯片TM1650,驅動芯片與DSP之間只需要兩個IO口就可以實現(xiàn)數(shù)碼管的控制,還是非常方便的。
另外,該芯片通過讀的方式能夠檢測外部的按鍵。
2、TM1650介紹
TM1650是一款國產4位共陰數(shù)碼管驅動芯片,它還帶有矩陣按鍵掃碼功能。它的基本參數(shù)如下:
-
工作電壓:3~5V
-
數(shù)碼管驅動模式:8段x4位共陰數(shù)碼管
-
矩陣按鍵驅動模式:7x4矩陣按鍵,不支持組合鍵
-
通信接口:類IIC,使用了IIC相同的時序,但沒有完全遵守IIC的協(xié)議,不帶從機地址
引腳定義
SCL:串行通信時鐘線
SDA:串行通信數(shù)據(jù)線
做數(shù)碼管驅動使用時
TM1650使用的是類IIC接口,只是不帶從機地址機制。所以總線上的基本信號也包含起始信號,ACK應答,結束信號,同時字節(jié)數(shù)據(jù)發(fā)送時,也是按照標準IIC的MSB First順序。
發(fā)送命令設置數(shù)碼管顯示工作參數(shù)
通信格式:起始信號,模式命令(1字節(jié)),顯示命令(1字節(jié)),結束信號
這個指令用于設置數(shù)碼管顯示的相關參數(shù)。例如亮度,7段或者8段顯示,顯示的開關。模式命令固定為0x48,而顯示命令則滿足以下格式:
3、設計思路
計時:因為勇士027系列dsp沒有硬件RTC模塊,所以只能使用硬件定時器來實現(xiàn)。使用cputimer0來設置1ms的周期中斷,在中斷里面進行計數(shù),計數(shù)到1s后進行更新數(shù)碼管顯示。
暫停功能:利用按鍵s101來實現(xiàn)計數(shù)的暫停與繼續(xù)。
亮度調節(jié)功能:利用按鍵s102來實現(xiàn)數(shù)碼管亮度的調節(jié)
計數(shù)復位功能:利用按鍵s103來實現(xiàn)計數(shù)值的復位,從零開始計時
三、代碼編寫
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;
int main(void)
{
uint16_t cnt = 0;
InitSysCtrl();
InitFlash();
InitSciGpio();
DINT;
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
Scia_Config(9600);
Timer0_init();
InitI2C_Gpio();
I2CA_Init();
softResetIIC_BUS();
LigntVal = 0x11;
TM1650_Send(CMD_SEG, LigntVal);
TM1650_Send(DIG0, SEG7Table[0]);
TM1650_Send(DIG1, SEG7Table[0]);
TM1650_Send(DIG2, SEG7Table[0]);
TM1650_Send(DIG3, SEG7Table[0]);
EINT;
InitKEY();
InitLED();
Scia_Print("Hello haawking!\r\n");
while(1)
{
if((CpuTimer0.InterruptCount % 250) == 0)
{
TM1650_Read(CMD_KEY, &keyVal);
if(keyVal == 0x44)
{
msec_cnt_on ^= 0x01;
uart_printf("msec_cnt_on = %d\r\n",msec_cnt_on);
}
if(keyVal == 0x4c)
{
LigntVal = (LigntVal + 0x20) & 0x7F;
TM1650_Send(CMD_SEG, LigntVal);
uart_printf("LigntVal = %d\r\n",LigntVal);
}
if(keyVal == 0x54)
{
msec_cnt = 0;
sec_rtc = 0;
min_rtc = 0;
keyReg = 0;
TM1650_Send(DIG0,SEG7Table[0]);
TM1650_Send(DIG1, SEG7Table[0]);
TM1650_Send(DIG2, SEG7Table[0]);
TM1650_Send(DIG3, SEG7Table[0]);
GpioDataRegs.GPATOGGLE.bit.GPIO7 = 1;
uart_printf("cnt reset\r\n");
}
}
if(msec_cnt >= 1000)
{
msec_cnt = 0;
GpioDataRegs.GPATOGGLE.bit.GPIO6 = 1;
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
/******************************************************************
*函數(shù)名:Timer0_init
*參 數(shù):無
*返回值:無
*作 用:初始化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;
/*重映射中斷服務函數(shù)*/
EALLOW;
PieVectTable.TINT0 = &cpu_timer0_isr;
EDIS;
/*連接CPU中斷Y*/
IER |= M_INT1;
/*連接Y中斷里的第幾位*/
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
}
/******************************************************************
*函數(shù)名:INTERRUPT void cpu_timer0_isr(void)
*參 數(shù):無
*返回值:無
*作 用:CPU 定時器0 中斷服務函數(shù)
******************************************************************/
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中斷次數(shù)累計*/
CpuTimer0.InterruptCount++;
if(msec_cnt_on == 0)
{
msec_cnt++;
}
/*檢測IIC模塊狀態(tài)為空閑還是寫入*/
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;
}
評論