RP2350 HSTX – 实战分析SPI模拟

/ 0评 / 0

这里就是分析官方例子,首先官方代码第一步就先调整时钟到USB PLL,因为系统PLL实在太猛了.

    reset_block(RESETS_RESET_HSTX_BITS);
    hw_write_masked(
        &clocks_hw->clk[clk_hstx].ctrl,
        CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB << CLOCKS_CLK_HSTX_CTRL_AUXSRC_LSB,
        CLOCKS_CLK_HSTX_CTRL_AUXSRC_BITS
    );
    unreset_block_wait(RESETS_RESET_HSTX_BITS);

抓的时钟线是50MHz.

因为他的定义是这样的.

看一下寄存器上的配置.

可见DC和CS也要编码进TXFIFO里,那么究竟编码到哪里,继续分析.

static inline void lcd_put_dc_cs_data(bool dc, bool csn, uint8_t data) {
	hstx_put_word(
		(uint32_t)data |
		(csn ? 0x0ff00000u : 0x00000000u) |
		// Note DC gets inverted inside of HSTX:
		(dc  ? 0x00000000u : 0x0003fc00u)
	);
}

当10-17位为高时,DC输出0,因为DC在设置时候进行了反向.在这里这样设置就可以免去软件逻辑上的反向,逻辑更清晰.20-27为高时,CS输出高,否则输出低,我们看得到,他们都占了8位,是因为我们SPI就是移动8位的,他移动的8位期间内不要任何变化.现在再看这两行是不是就明白了.

    hstx_ctrl_hw->bit[PIN_CS - FIRST_HSTX_PIN] =
        (27u << HSTX_CTRL_BIT0_SEL_P_LSB) |
        (27u << HSTX_CTRL_BIT0_SEL_N_LSB);

    hstx_ctrl_hw->bit[PIN_DC - FIRST_HSTX_PIN] =
        (17u << HSTX_CTRL_BIT0_SEL_P_LSB) |
        (17u << HSTX_CTRL_BIT0_SEL_N_LSB) |
        (HSTX_CTRL_BIT0_INV_BITS);

再者,DIN即MOSI,他设定为7,那么就是0-7是数据.

    hstx_ctrl_hw->bit[PIN_DIN - FIRST_HSTX_PIN] =
        (7u << HSTX_CTRL_BIT0_SEL_P_LSB) |
        (7u << HSTX_CTRL_BIT0_SEL_N_LSB);

刚好也是最低位.

为了证明我们真的学废了,我们试着改成6bit SPI.

代码


    hstx_ctrl_hw->bit[PIN_SCK - FIRST_HSTX_PIN] =
        HSTX_CTRL_BIT0_CLK_BITS;

    hstx_ctrl_hw->bit[PIN_DIN - FIRST_HSTX_PIN] =
        (5u << HSTX_CTRL_BIT0_SEL_P_LSB) |
        (5u << HSTX_CTRL_BIT0_SEL_N_LSB);

    hstx_ctrl_hw->bit[PIN_CS - FIRST_HSTX_PIN] =
        (17u << HSTX_CTRL_BIT0_SEL_P_LSB) |
        (17u << HSTX_CTRL_BIT0_SEL_N_LSB);

    hstx_ctrl_hw->bit[PIN_DC - FIRST_HSTX_PIN] =
        (11u << HSTX_CTRL_BIT0_SEL_P_LSB) |
        (11u << HSTX_CTRL_BIT0_SEL_N_LSB) |
        (HSTX_CTRL_BIT0_INV_BITS);

    // We have packed 8-bit fields, so shift left 1 bit/cycle, 8 times.
    hstx_ctrl_hw->csr =
        HSTX_CTRL_CSR_EN_BITS |
        (31u << HSTX_CTRL_CSR_SHIFT_LSB) | // 每次移位1位,那么设置为31,因为32-1=31.
        (6u << HSTX_CTRL_CSR_N_SHIFTS_LSB) | // 每次从FIFO取出,可供移位送出的次数,比如8就是8bit spi串行出8位.
        (1u << HSTX_CTRL_CSR_CLKDIV_LSB); // 如果设置为2,那么CLK虽然只有一半,但是每次会移动2个位,上面设置6,实际成3bit SPI

发送数据测试.

    while (true) {
        lcd_put_dc_cs_data(true, true, 0x1f);
        for(uint8_t i = 0; i < 4; i++)
        {
            lcd_put_dc_cs_data(true, false, i);
        }
        lcd_put_dc_cs_data(true, true, 0x1f);
        sleep_us(5);
    }

实际测试

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注