#include "bat32g137.h"
#include "userdefine.h"
#include "clk.h"
#include "tmm.h"
/***********************************************************************************************************************
* Function Name: TMM0_Init
* Description : This function initializes the TMM0 module.
* Arguments : None
* Return Value : None
***********************************************************************************************************************/
void TMM0_Init(void)
{
// 開啓時鐘
CGC->PER1 |= CGC_PER1_TMMEN_Msk; /* enables input clock supply */
// 匹配後不清除定時器
TMM->TMSTR |= _04_TMM_TM0_COUNT_CONTINUES;
// 停止定時器
TMM->TMSTR &= (uint8_t)~_01_TMM_TM0_COUNT_START;
// D作爲B的緩衝區
// C作爲A的緩衝區
TMM->TMMR |= _10_TMM_TMGRC0_BUFFER | _20_TMM_TMGRD0_BUFFER;
// 時鐘源是 FHOCO
TMM->TMCR0 = _00_TMM_COUNTER_CLEAR_DISABLE | _00_TMM_INETNAL_CLOCK_FCLK_FHOCO;
// 捕獲模式 上升沿
TMM->TMIORA0 = _40_TMM_TMGRB_CAPTURE | _00_TMM_TMGRB_CAPTURE_RISING | _04_TMM_TMGRA_CAPTURE | _00_TMM_TMGRA_CAPTURE_RISING;
TMM->TMIORC0 |= _40_TMM_TMGRD_CAPTURE | _04_TMM_TMGRC_CAPTURE;
// 開啓對應的中斷
TMM->TMIER0 = _10_TMM_OVIE_ENABLE | _08_TMM_IMID_ENABLE | _02_TMM_IMIB_ENABLE | _01_TMM_IMIA_ENABLE;
TMM->TMPOCR0 = _00_TMIOD_OUTPUT_ACTIVE_L | _00_TMIOC_OUTPUT_ACTIVE_L | _00_TMIOB_OUTPUT_ACTIVE_L;
// 初始化IO爲輸入模式
/* Set TMIOA0 pin */
PORT->PM1 |= 0x80U; // P17
/* Set TMIOB0 pin */
PORT->PM1 |= 0x10U; // P14
}
/***********************************************************************************************************************
* Function Name: TMM0_Start
* Description : This function starts TMM0 counter.
* Arguments : None
* Return Value : None
***********************************************************************************************************************/
void TMM0_Start(void)
{
volatile uint8_t tmsr_dummy;
// 清除掛起
INTC_ClearPendingIRQ(TMM0_IRQn);/* clear INTTMM0 interrupt flag */
// 讀取狀態寄存器 讀取清除狀態寄存器數據
tmsr_dummy = TMM->TMSR0; /* read TMSR0 before write 0 */
TMM->TMSR0 = 0x00U; /* clear TM0 each interrupt request */
// 開啓使能
INTC_EnableIRQ(TMM0_IRQn);/* enable INTTMM0 interrupt */
// 啓動定時器
TMM->TMSTR |= _01_TMM_TM0_COUNT_START;
}
/***********************************************************************************************************************
* Function Name: pulse_out_init
* Description : This function initializes the pulse out module.
* Arguments : None
* Return Value : None
***********************************************************************************************************************/
static void pulse_out_init(void)
{
//禁止輸出
PCBZ->CKS0 &= (uint8_t)~0x80;
PCBZ->CKS0 = 0x07; // 5.86K 170us
/* Set CLKBUZ0 pin */
PORT->P14 &= 0xFEU;
PORT->PM14 &= 0xFEU; // P140
// 使能輸出
PCBZ->CKS0 |= 0x80;
}
// beep 功能產生方波
int main(void)
{
TMM0_Init();
TMM0_Start();
pulse_out_init();
while(1)
{
}
}
void IRQ27_Handler(void) __attribute__((alias("tmm0_interrupt")));
volatile uint32_t g_tmm0_active_width_a = 0UL;
volatile uint32_t g_tmm0_inactive_width_a = 0UL;
volatile uint32_t g_tmm0_active_width_b = 0UL;
volatile uint32_t g_tmm0_inactive_width_b = 0UL;
volatile uint32_t g_tmm0_active_width_c = 0UL;
volatile uint32_t g_tmm0_inactive_width_c = 0UL;
volatile uint32_t g_tmm0_active_width_d = 0UL;
volatile uint32_t g_tmm0_inactive_width_d = 0UL;
volatile uint32_t g_tmm0_active_width_elc = 0UL;
volatile uint32_t g_tmm0_inactive_width_elc = 0UL;
volatile uint16_t g_tmm0_tmgra_old = 0U;
volatile uint16_t g_tmm0_tmgrb_old = 0U;
volatile uint8_t g_tmm0_ovf_a = 0U;
volatile uint8_t g_tmm0_ovf_b = 0U;
/***********************************************************************************************************************
* Function Name: tmm0_interrupt
* Description : None
* Arguments : None
* Return Value : None
***********************************************************************************************************************/
static void tmm0_interrupt(void)
{
// 首先清除掛起
INTC_ClearPendingIRQ(TMM0_IRQn); /* clear INTTMM0 interrupt flag */
uint8_t tmsr0_temp = TMM->TMSR0;
// 讀取數據
uint16_t tmm_pul_a_cur = TMM->TMGRA0;
uint16_t tmm_pul_b_cur = TMM->TMGRB0;
uint8_t tmier0_temp = TMM->TMIER0;
// 關閉中斷
TMM->TMIER0 = 0x00U;
if ((TMM->TMSR0 & _10_TMM0_INTOV_GENERATE_FLAG) == _10_TMM0_INTOV_GENERATE_FLAG)
{
TMM->TMSR0 = tmsr0_temp & (uint8_t)~_10_TMM0_INTOV_GENERATE_FLAG;
// 記錄溢出次數
g_tmm0_ovf_a += 1U;
g_tmm0_ovf_b += 1U;
}
if ((TMM->TMSR0 & _01_TMM0_INTA_GENERATE_FLAG) == _01_TMM0_INTA_GENERATE_FLAG)
{
// 清狀態
TMM->TMSR0 = tmsr0_temp & (uint8_t)~_01_TMM0_INTA_GENERATE_FLAG;
if (g_tmm0_ovf_a == 0U)
{
//g_tmm0_active_width_a = (uint32_t)((uint32_t)tmm_pul_a_cur - (uint32_t)g_tmm0_tmgra_old);
g_tmm0_active_width_a = (uint32_t)((uint32_t)tmm_pul_a_cur - (uint32_t)TMM->TMGRC0);
}
else
{
// g_tmm0_active_width_a = (uint32_t)(0x10000UL * (uint32_t)g_tmm0_ovf_a - (uint32_t)g_tmm0_tmgra_old +
// (uint32_t)tmm_pul_a_cur);
g_tmm0_active_width_a = (uint32_t)(0x10000UL * (uint32_t)g_tmm0_ovf_a - (uint32_t)TMM->TMGRC0 +
(uint32_t)tmm_pul_a_cur);
g_tmm0_ovf_a = 0U;
}
g_tmm0_inactive_width_a = 0UL;
g_tmm0_tmgra_old = tmm_pul_a_cur;
}
if ((TMM->TMSR0 & _02_TMM0_INTB_GENERATE_FLAG) == _02_TMM0_INTB_GENERATE_FLAG)
{
TMM->TMSR0 = tmsr0_temp & (uint8_t)~(_02_TMM0_INTB_GENERATE_FLAG);
if (g_tmm0_ovf_b == 0U)
{
g_tmm0_active_width_b = (uint32_t)((uint32_t)tmm_pul_b_cur - (uint32_t)g_tmm0_tmgrb_old);
}
else
{
g_tmm0_active_width_b = (uint32_t)(0x10000UL * (uint32_t)g_tmm0_ovf_b - (uint32_t)g_tmm0_tmgrb_old +
(uint32_t)tmm_pul_b_cur);
g_tmm0_ovf_b = 0U;
}
g_tmm0_inactive_width_b = 0UL;
g_tmm0_tmgrb_old = tmm_pul_b_cur;
}
TMM->TMIER0 = tmier0_temp;
}
嘗試兩種用緩衝區不用緩衝區,測試時間都很準確,170u的數據。
8192/48 = 170us.
開啓緩衝區,緩衝區和timerb一樣,緩衝區的數據可以理解就是上一次的數據。
程序中有一個用了讀緩衝來提取的有一個沒有,測試都很準確,其中很重要的一點,進入中斷過後,程序立馬讀取了數據。因爲這些寄存器會一直在變。開緩衝的意義就在這裏。