To be completed!
# 嵌入式系統設計:實驗 3
在這個實驗中,LCD 顯示器是主要的重點。因此,了解其底層硬體以及資料傳輸的方法是至關重要的。
void init_SPI3(void) {
/*
* 設定為主裝置(master),時鐘閒置時為低電位(clock idle low),傳輸為 9 位元(9-bit transaction),
* 在時鐘下降緣(falling edge)輸出資料,在時鐘上升緣(rising edge)擷取輸入資料。
* 設定 IP 時鐘除頻器(clock divider)。SPI 時脈速率為 1MHz
*/
SPI_Open(SPI3, SPI_MASTER, SPI_MODE_0, 9, 1000000);
SPI_DisableAutoSS(SPI3);
}
# LCD 的詳細功能
/* SPI_T::SSR: SSR Position */
#define SPI_SSR_SSR_Pos 0
/* Select SPIn_SS0 */
#define SPI_SS0 (1<<SPI_SSR_SSR_Pos)
/* SPI_T::SSR: AUTOSS Position, Mask */
#define SPI_SSR_AUTOSS_Pos 3
#define SPI_SSR_AUTOSS_Msk (1ul << SPI_SSR_AUTOSS_Pos)
/* SPI_T::SSR: SS_LVL Position, Mask */
#define SPI_SSR_SS_LVL_Pos 2
#define SPI_SSR_SS_LVL_Msk (1ul << SPI_SSR_SS_LVL_Pos)
/* SPI_T::CNTRL: GO_BUSY Position, Mask */
#define SPI_CNTRL_GO_BUSY_Pos 0
#define SPI_CNTRL_GO_BUSY_Msk (1ul << SPI_CNTRL_GO_BUSY_Pos)
/**
* @brief Set SPIn_SS0 pin to low state.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Disable automatic slave selection function and set SPIn_SS0 pin to low state. Only available in Master mode.
*/
#define SPI_SET_SS0_LOW(spi) \
((spi)->SSR = ((spi)->SSR & ~(SPI_SSR_AUTOSS_Msk|SPI_SSR_SS_LVL_Msk|SPI_SS0)) | SPI_SS0)
/**
* @brief Set SPIn_SS0 pin to high state.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details Disable automatic slave selection function and set SPIn_SS0 pin to high state. Only available in Master mode.
*/
#define SPI_SET_SS0_HIGH(spi) \
((spi)->SSR = ((spi)->SSR & ~(SPI_SSR_AUTOSS_Msk|SPI_SSR_SS_LVL_Msk|SPI_SS0)))
/**
* @brief Write datum to TX0 register.
* @param[in] spi The pointer of the specified SPI module.
* @param[in] u32TxData The datum which user attempt to transfer through SPI bus.
* @return None.
* @details Write u32TxData to TX0 register.
*/
#define SPI_WRITE_TX0(spi, u32TxData) ((spi)->TX[0] = (u32TxData))
/**
* @brief Set the GO_BUSY bit to trigger SPI transfer.
* @param[in] spi The pointer of the specified SPI module.
* @return None.
* @details If FIFO mode is disabled, user can use this macro to trigger the data transfer after all configuration is ready.
* If FIFO mode is enabled, user should not use this macro to trigger the data transfer. SPI controller will trigger the data transfer
* automatically after user write to SPI_TX0/1 register.
*/
#define SPI_TRIGGER(spi) ((spi)->CNTRL |= SPI_CNTRL_GO_BUSY_Msk)
/**
* @brief Get the SPI busy state.
* @param[in] spi The pointer of the specified SPI module.
* @retval 0 SPI controller is not busy.
* @retval 1 SPI controller is busy.
* @details This macro will return the busy state of SPI controller.
*/
#define SPI_IS_BUSY(spi) \
( ((spi)->CNTRL & SPI_CNTRL_GO_BUSY_Msk) >> SPI_CNTRL_GO_BUSY_Pos )
# 提供給我們使用的函式
void lcdWriteCommand(unsigned char temp)
{
SPI_SET_SS0_LOW(SPI3); /* Manually select slave */
SPI_WRITE_TX0(SPI3, temp); /* Write Data */
SPI_TRIGGER(SPI3); /* Trigger SPI data transfer */
while (SPI_IS_BUSY(SPI3)); /* Check SPI3 busy status */
SPI_SET_SS0_HIGH(SPI3); /* Manually deselect slave */
}
/* Write data to LCD */
void lcdWriteData(uint8_t temp)
{
SPI_SET_SS0_LOW(SPI3); /* Manually select slave */
SPI_WRITE_TX0(SPI3, 0x100 + temp); /* Write Data */
SPI_TRIGGER(SPI3); /* Trigger SPI data transfer */
while (SPI_IS_BUSY(SPI3)); /* Check SPI3 busy status */
SPI_SET_SS0_HIGH(SPI3); /* Manually deselect slave */
}
/* Set Address to LCD */
void lcdSetAddr(uint8_t PageAddr, uint8_t ColumnAddr)
{
/* Set Page Address */
SPI_SET_SS0_LOW(SPI3);
SPI_WRITE_TX0(SPI3, 0xB0 | PageAddr);
SPI_TRIGGER(SPI3);
while (SPI_IS_BUSY(SPI3));
SPI_SET_SS0_HIGH(SPI3);
/* Set Most Significant Hex of Column Address */
SPI_SET_SS0_LOW(SPI3);
SPI_WRITE_TX0(SPI3, 0x10 | (ColumnAddr >> 4) & 0xF);
SPI_TRIGGER(SPI3);
while (SPI_IS_BUSY(SPI3));
SPI_SET_SS0_HIGH(SPI3);
/* Set Least Significant Hex of Column Address */
SPI_SET_SS0_LOW(SPI3);
SPI_WRITE_TX0(SPI3, 0x00 | (ColumnAddr & 0xF));
SPI_TRIGGER(SPI3);
while (SPI_IS_BUSY(SPI3));
SPI_SET_SS0_HIGH(SPI3);
}
#define LCD_Xmax 128
#define LCD_Ymax 64
void draw_LCD(unsigned char *buffer)
{
uint8_t x, y;
for (x = 0; x < LCD_Xmax; x++)
{
for (y = 0; y < (LCD_Ymax / 8); y++)
{
lcdSetAddr(y, (LCD_Xmax + 1 - x));
lcdWriteData(buffer[x + y * LCD_Xmax]);
}
}
}
Questions:
- In
init_SPI3(void), why is SPI3 configured for a 9-bit transaction? (Think aboutSPI_WRITE_TX0) - Why are additional operations being added to the parameters of
SPI_WRITE_TX0()? - Look up the definition and the type of
SPI3and tell where the following statuses are recorded?GO_BUSY,SS_LVL,AUTOSS- It should be easy if you find out the type definition of
SPI_T.
- Find out all possible results of
SPI_IS_BUSY(SPI3).
# 實作
我們組做了貪吃蛇小遊戲,用到的元件有: LCD, buzzer, keypad