这里就是分析官方例子,首先官方代码第一步就先调整时钟到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.

因为他的定义是这样的.
- BIT0 = DIN
- BIT1 = SCK
- BIT2 = CS
- BIT3 = DC
看一下寄存器上的配置.

可见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.
- 0 - 5 存放 SPI 数据
- 6 - 11 存放 DC 状态
- 12 - 17 存放 CS 状态
代码
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);
}
实际测试
