QDTRANS bit for quadrature decoder

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can configure the quadrature decoder correctly using this code (it's a SAME70, but that shouldn't matter) :

	pmc_enable_periph_clk(ID_TC6);
	pmc_enable_periph_clk(ID_TC7);
	tc_init(TC2, 0, TC_CMR_TCCLKS_XC0
		| TC_CMR_ETRGEDG_RISING | TC_CMR_ABETRG // Reset TC6 and increment TC7 on encoder index
		);
	tc_set_block_mode(TC2, TC_BMR_QDEN | TC_BMR_POSEN
//		| TC_BMR_QDTRANS		// don't use direction, always increment
//		| TC_BMR_EDGPHA			// to have 360 000 pts per rotation
		);
	tc_start(TC2, 0);
	tc_start(TC2, 1);

 

Then I use another Timer to read the position periodically:

    uint32_t ul_div = 0;
    uint32_t ul_tc_clks = 0;
    uint32_t ul_sysclk = sysclk_get_peripheral_hz();

    pmc_disable_pck(PMC_PCK_6);
    pmc_switch_pck_to_mck(PMC_PCK_6, PMC_PCK_PRES(1));
    pmc_enable_pck(PMC_PCK_6);

    pmc_enable_periph_clk(ID_TC1);

    /* Configure TC for frequency and trigger on RC compare. */
    tc_find_mck_divisor(32000, ul_sysclk, &ul_div, &ul_tc_clks, ul_sysclk);
    tc_init(TC0, 1, ul_tc_clks | TC_CMR_WAVSEL_UP_RC | TC_CMR_WAVE);
    tc_write_rc(TC0, 1, (ul_sysclk / ul_div) / 32000);

    /* Configure and enable interrupt on RC compare. */
	NVIC_SetPriority(ID_TC1, IRQ_PRIOR_ENCODER);
	NVIC_EnableIRQ((IRQn_Type)ID_TC1);
	tc_enable_interrupt(TC0, 1, TC_IER_CPCS);

With this handler:

void TC1_Handler(void) {
	uint32_t ul_status;
	uint32_t val;

	/* Read TC1 Status. */
	ul_status = tc_get_status(TC0, 1);

	/* RC compare. */
	if (((ul_status & TC_SR_CPCS) == TC_SR_CPCS)) {
		val = tc_read_cv(TC2, 0);

		encoder_buffer[++index_buffer] = val
	}
}

 

Until here, no problem.

Now what I'd like is to do is to count what ever the rotation direction is. If I understand correctly, it's the goal of the QDTRANS bit in TC_CMR. But when I activate it (just uncomment the line in timer initialization), the decoder behaves very strangely. From what I see, TC2 increments or decrements according to TIOA6 / TIOB7: When TIOA0 is low, it's not updated, when TIOA0 is high, it increments if TIOB0 is high or decrements if TIOB0 is low. It increments / decrements at 150MHz (peripheral clock).

The fact is that it doesn't count edges at all, but increments or decrements according to levels. There is probably something I don't understand about this QDTRANS usage. Any idea how to use it?

 

Thanks

Last Edited: Mon. May 23, 2016 - 11:40 AM