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:

  1. In init_SPI3(void) , why is SPI3 configured for a 9-bit transaction? (Think about SPI_WRITE_TX0 )
  2. Why are additional operations being added to the parameters of SPI_WRITE_TX0() ?
  3. Look up the definition and the type of SPI3 and 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 .
  4. Find out all possible results of SPI_IS_BUSY(SPI3) .

# 實作

我們組做了貪吃蛇小遊戲,用到的元件有: LCD, buzzer, keypad