- static void SPI1_GPIO_Configuration(void)
- {
- GPIO_InitType GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(SPI1_GPIO_CLK|RCC_APB2PERIPH_SPI1|RCC_APB2PERIPH_AFIO, ENABLE);
-
- /* Configure SPI_FLASH pins*/
- GPIO_InitStructure.GPIO_Pins = SPI1_PIN_MOSI;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(SPI1_GPIO, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pins = SPI1_PIN_MISO;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(SPI1_GPIO, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pins = SPI1_PIN_SCK;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(SPI1_GPIO, &GPIO_InitStructure);
-
- //CS
- GPIO_InitStructure.GPIO_Pins = LCD_CS_PIN;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;
- GPIO_Init(LCD_CS_GPIO, &GPIO_InitStructure);
-
- }
- //SPI1 初始化
- void SPI1_Init(void)
- {
- SPI_InitType SPI_InitStructure;
-
- /* Enable SPIy clock and GPIO clock for SPIy and SPIz */
- RCC_APB2PeriphClockCmd(SPI1_CLK , ENABLE);
- /* 1st phase: SPI1 Master */
- /* GPIO configuration ------------------------------------------------------*/
- SPI1_GPIO_Configuration();
-
- //CS 置高
- __LCD_CS_SET();
-
- /* SPI1 Config -------------------------------------------------------------*/
- SPI_DefaultInitParaConfig(&SPI_InitStructure);
- SPI_InitStructure.SPI_TransMode = SPI_TRANSMODE_FULLDUPLEX;
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2EDGE;
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_HIGH;
- SPI_InitStructure.SPI_CPOLY = 0;
- SPI_InitStructure.SPI_FirstBit = SPI_FIRSTBIT_MSB;
- SPI_InitStructure.SPI_FrameSize = SPI_FRAMESIZE_8BIT;
- SPI_InitStructure.SPI_MCLKP = SPI_MCLKP_8;
-
- //SPI_InitStructure.SPI_MCLKP = SPI_MCLKP_32;
-
-
- SPI_InitStructure.SPI_NSSSEL = SPI_NSSSEL_SOFT;
- SPI_InitStructure.SPI_Mode = SPI_MODE_MASTER;
-
- SPI_Init(SPI1, &SPI_InitStructure);
-
- /* Enable SPI1 */
- SPI_Enable(SPI1, ENABLE);
- }
配置好了后,我们单独写一个SPI读写一个字节的函数:
- unsigned int SPI1ReadWriteByte(unsigned char tx_data)
- {
-
- /* Wait for SPIy Tx buffer empty */
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TE) == RESET);
- /* Send SPIy data */
- SPI_I2S_TxData(SPI1,tx_data);
- /* Wait for SPIy data reception */
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RNE) == RESET);
- /* Read SPIy received data */
- return SPI_I2S_RxData(SPI1);
-
- }
我们定义LCD的读写,直接调用SPI1的读写函数:
- #define __LCD_WRITE_BYTE(__DATA) SPI1ReadWriteByte(__DATA)
其中LCD的其他几个控制引脚的配置,与JTAG的引脚有冲突,我们remap为SWD调试模式,释放PA15 PB3 PB4 3个引脚作为普通引脚:
- void lcd_port_init(void)
- {
- GPIO_InitType GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOA| RCC_APB2PERIPH_GPIOC||RCC_APB2PERIPH_AFIO , ENABLE);
- //调试仅SWD
- GPIO_PinsRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//释放PA15 PB3 PB4
-
- GPIO_StructInit(&GPIO_InitStructure);
- //LCD-CS PA15
- GPIO_InitStructure.GPIO_Pins = LCD_CS_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_Init(LCD_CS_GPIO, &GPIO_InitStructure);
- //LCD-DC PA8
- GPIO_InitStructure.GPIO_Pins = LCD_DC_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_Init(LCD_DC_GPIO, &GPIO_InitStructure);
- //LCD-BKL PC7
- GPIO_InitStructure.GPIO_Pins = LCD_BKL_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_Init(LCD_BKL_GPIO, &GPIO_InitStructure);
- }
LCD其他操作函数:
- void lcd_write_byte(uint8_t chByte, uint8_t chCmd)
- {
- if (chCmd) {
- __LCD_DC_SET();
- } else {
- __LCD_DC_CLR();
- }
-
- __LCD_CS_CLR();
- __LCD_WRITE_BYTE(chByte);
- __LCD_CS_SET();
- }
- void lcd_write_word(uint16_t hwData)
- {
- __LCD_DC_SET();
- __LCD_CS_CLR();
- __LCD_WRITE_BYTE(hwData >> 8);
- __LCD_WRITE_BYTE(hwData & 0xFF);
- __LCD_CS_SET();
- }
- void lcd_write_register(uint8_t chRegister, uint8_t chValue)
- {
- lcd_write_byte(chRegister, LCD_CMD);
- lcd_write_byte(chValue, LCD_DATA);
- }
- //set the specified position of cursor on lcd.
- //hwXpos specify x position
- //hwYpos specify y position
- void lcd_set_cursor(uint16_t hwXpos, uint16_t hwYpos)
- {
- if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
- return;
- }
-
- lcd_write_register(0x02, hwXpos >> 8);
- lcd_write_register(0x03, hwXpos & 0xFF); //Column Start
- lcd_write_register(0x06, hwYpos >> 8);
- lcd_write_register(0x07, hwYpos & 0xFF); //Row Start
- }
- //clear the lcd with the specified color.
- void lcd_clear_screen(uint16_t hwColor)
- {
- uint32_t i, wCount = LCD_WIDTH;
-
- wCount *= LCD_HEIGHT;
-
- lcd_set_cursor(0, 0);
- lcd_write_byte(0x22, LCD_CMD);
-
- __LCD_DC_SET();
- __LCD_CS_CLR();
- for (i = 0; i < wCount; i ++) {
- __LCD_WRITE_BYTE(hwColor >> 8);
- __LCD_WRITE_BYTE(hwColor & 0xFF);
- }
- __LCD_CS_SET();
- }
- //draw a point on the lcd with the specified color.
- //hwXpos specify x position.
- //hwYpos specify y position.
- //hwColor color of the point.
- void lcd_draw_point(uint16_t hwXpos, uint16_t hwYpos, uint16_t hwColor)
- {
- if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
- return;
- }
-
- lcd_set_cursor(hwXpos, hwYpos);
- lcd_write_byte(0x22, LCD_CMD);
- lcd_write_word(hwColor);
- }
- //display a char at the specified position on lcd.
- void lcd_display_char(uint16_t hwXpos, //specify x position.
- uint16_t hwYpos, //specify y position.
- uint8_t chChr, //a char is display.
- uint8_t chSize, //specify the size of the char
- uint16_t hwColor) //specify the color of the char
- {
- uint8_t i, j, chTemp;
- uint16_t hwYpos0 = hwYpos, hwColorVal = 0;
- if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
- return;
- }
-
- for (i = 0; i < chSize; i ++) {
- if (FONT_1206 == chSize) {
- chTemp = c_chFont1206[chChr - 0x20][i];
- } else if (FONT_1608 == chSize) {
- chTemp = c_chFont1608[chChr - 0x20][i];
- }
-
- for (j = 0; j < 8; j ++) {
- if (chTemp & 0x80) {
- hwColorVal = hwColor;
- lcd_draw_point(hwXpos, hwYpos, hwColorVal);
- }
- chTemp <<= 1;
- hwYpos ++;
- if ((hwYpos - hwYpos0) == chSize) {
- hwYpos = hwYpos0;
- hwXpos ++;
- break;
- }
- }
- }
- }
- //_pow
- uint32_t _pow(uint8_t m, uint8_t n)
- {
- uint32_t result = 1;
-
- while(n --) result *= m;
- return result;
- }
- //display a number at the specified position on lcd.
- void lcd_display_num(uint16_t hwXpos, //specify x position.
- uint16_t hwYpos, //specify y position.
- uint32_t chNum, //a number is display.
- uint8_t chLen, //length ot the number
- uint8_t chSize, //specify the size of the number
- uint16_t hwColor) //specify the color of the number
- {
- uint8_t i;
- uint8_t chTemp, chShow = 0;
- if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
- return;
- }
-
- for(i = 0; i < chLen; i ++) {
- chTemp = (chNum / _pow(10, chLen - i - 1)) % 10;
- if(chShow == 0 && i < (chLen - 1)) {
- if(chTemp == 0) {
- lcd_display_char(hwXpos + (chSize / 2) * i, hwYpos, ' ', chSize, hwColor);
- continue;
- } else {
- chShow = 1;
- }
- }
- lcd_display_char(hwXpos + (chSize / 2) * i, hwYpos, chTemp + '0', chSize, hwColor);
- }
- }
- //display a string at the specified position on lcd.
- void lcd_display_string(uint16_t hwXpos, //specify x position.
- uint16_t hwYpos, //specify y position.
- const uint8_t *pchString, //a pointer to string
- uint8_t chSize, // the size of the string
- uint16_t hwColor) // specify the color of the string
- {
- if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
- return;
- }
-
- while (*pchString != '\0') {
- if (hwXpos > (LCD_WIDTH - chSize / 2)) {
- hwXpos = 0;
- hwYpos += chSize;
- if (hwYpos > (LCD_HEIGHT - chSize)) {
- hwYpos = hwXpos = 0;
- lcd_clear_screen(0x00);
- }
- }
-
- lcd_display_char(hwXpos, hwYpos, (uint8_t)*pchString, chSize, hwColor);
- hwXpos += chSize / 2;
- pchString ++;
- }
- }
- //draw a line at the specified position on lcd.
- void lcd_draw_line(uint16_t hwXpos0, //specify x0 position.
- uint16_t hwYpos0, //specify y0 position.
- uint16_t hwXpos1, //specify x1 position.
- uint16_t hwYpos1, //specify y1 position.
- uint16_t hwColor) //specify the color of the line
- {
- int x = hwXpos1 - hwXpos0;
- int y = hwYpos1 - hwYpos0;
- int dx = abs(x), sx = hwXpos0 < hwXpos1 ? 1 : -1;
- int dy = -abs(y), sy = hwYpos0 < hwYpos1 ? 1 : -1;
- int err = dx + dy, e2;
- if (hwXpos0 >= LCD_WIDTH || hwYpos0 >= LCD_HEIGHT || hwXpos1 >= LCD_WIDTH || hwYpos1 >= LCD_HEIGHT) {
- return;
- }
-
- for (;;){
- lcd_draw_point(hwXpos0, hwYpos0 , hwColor);
- e2 = 2 * err;
- if (e2 >= dy) {
- if (hwXpos0 == hwXpos1) break;
- err += dy; hwXpos0 += sx;
- }
- if (e2 <= dx) {
- if (hwYpos0 == hwYpos1) break;
- err += dx; hwYpos0 += sy;
- }
- }
- }
- //draw a circle at the specified position on lcd.
- void lcd_draw_circle(uint16_t hwXpos, //specify x position.
- uint16_t hwYpos, //specify y position.
- uint16_t hwRadius, //specify the radius of the circle.
- uint16_t hwColor) //specify the color of the circle.
- {
- int x = -hwRadius, y = 0, err = 2 - 2 * hwRadius, e2;
- if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
- return;
- }
-
- do {
- lcd_draw_point(hwXpos - x, hwYpos + y, hwColor);
- lcd_draw_point(hwXpos + x, hwYpos + y, hwColor);
- lcd_draw_point(hwXpos + x, hwYpos - y, hwColor);
- lcd_draw_point(hwXpos - x, hwYpos - y, hwColor);
- e2 = err;
- if (e2 <= y) {
- err += ++ y * 2 + 1;
- if(-x == y && e2 <= x) e2 = 0;
- }
- if(e2 > x) err += ++ x * 2 + 1;
- } while(x <= 0);
- }
- //fill a rectangle out at the specified position on lcd.
- void lcd_fill_rect(uint16_t hwXpos, //specify x position.
- uint16_t hwYpos, //specify y position.
- uint16_t hwWidth, //specify the width of the rectangle.
- uint16_t hwHeight, //specify the height of the rectangle.
- uint16_t hwColor) //specify the color of rectangle.
- {
- uint16_t i, j;
- if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
- return;
- }
-
- for(i = 0; i < hwHeight; i ++){
- for(j = 0; j < hwWidth; j ++){
- lcd_draw_point(hwXpos + j, hwYpos + i, hwColor);
- }
- }
- }
- //draw a vertical line at the specified position on lcd.
- void lcd_draw_v_line(uint16_t hwXpos, //specify x position.
- uint16_t hwYpos, //specify y position.
- uint16_t hwHeight, //specify the height of the vertical line.
- uint16_t hwColor) //specify the color of the vertical line.
- {
- uint16_t i, y1 = MIN(hwYpos + hwHeight, LCD_HEIGHT - 1);
- if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
- return;
- }
-
- for (i = hwYpos; i < y1; i ++) {
- lcd_draw_point(hwXpos, i, hwColor);
- }
- }
- //draw a horizonal line at the specified position on lcd.
- void lcd_draw_h_line(uint16_t hwXpos, //specify x position.
- uint16_t hwYpos, //specify y position.
- uint16_t hwWidth, //specify the width of the horizonal line.
- uint16_t hwColor) //specify the color of the horizonal line.
- {
- uint16_t i, x1 = MIN(hwXpos + hwWidth, LCD_WIDTH - 1);
- if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
- return;
- }
-
- for (i = hwXpos; i < x1; i ++) {
- lcd_draw_point(i, hwYpos, hwColor);
- }
- }
- void lcd_draw_rect(uint16_t hwXpos, //specify x position.
- uint16_t hwYpos, //specify y position.
- uint16_t hwWidth, //specify the width of the rectangle.
- uint16_t hwHeight, //specify the height of the rectangle.
- uint16_t hwColor) //specify the color of rectangle.
- {
- if (hwXpos >= LCD_WIDTH || hwYpos >= LCD_HEIGHT) {
- return;
- }
- lcd_draw_h_line(hwXpos, hwYpos, hwWidth, hwColor);
- lcd_draw_h_line(hwXpos, hwYpos + hwHeight, hwWidth, hwColor);
- lcd_draw_v_line(hwXpos, hwYpos, hwHeight, hwColor);
- lcd_draw_v_line(hwXpos + hwWidth, hwYpos, hwHeight + 1, hwColor);
- }
- //initialize the lcd.
- //phwDevId pointer to device ID of lcd
- void lcd_init(void)
- {
- // __LCD_RST_CLR();
- // delay_ms(100);
- // __LCD_RST_SET();
- __LCD_CS_SET();
- __LCD_BKL_SET();
- //Driving ability Setting
- lcd_write_register(0xEA,0x00); //PTBA[15:8]
- lcd_write_register(0xEB,0x20); //PTBA[7:0]
- lcd_write_register(0xEC,0x0C); //STBA[15:8]
- lcd_write_register(0xED,0xC4); //STBA[7:0]
- lcd_write_register(0xE8,0x38); //OPON[7:0]
- lcd_write_register(0xE9,0x10); //OPON1[7:0]
- lcd_write_register(0xF1,0x01); //OTPS1B
- lcd_write_register(0xF2,0x10); //GEN
- //Gamma 2.2 Setting
- lcd_write_register(0x40,0x01); //
- lcd_write_register(0x41,0x00); //
- lcd_write_register(0x42,0x00); //
- lcd_write_register(0x43,0x10); //
- lcd_write_register(0x44,0x0E); //
- lcd_write_register(0x45,0x24); //
- lcd_write_register(0x46,0x04); //
- lcd_write_register(0x47,0x50); //
- lcd_write_register(0x48,0x02); //
- lcd_write_register(0x49,0x13); //
- lcd_write_register(0x4A,0x19); //
- lcd_write_register(0x4B,0x19); //
- lcd_write_register(0x4C,0x16); //
- lcd_write_register(0x50,0x1B); //
- lcd_write_register(0x51,0x31); //
- lcd_write_register(0x52,0x2F); //
- lcd_write_register(0x53,0x3F); //
- lcd_write_register(0x54,0x3F); //
- lcd_write_register(0x55,0x3E); //
- lcd_write_register(0x56,0x2F); //
- lcd_write_register(0x57,0x7B); //
- lcd_write_register(0x58,0x09); //
- lcd_write_register(0x59,0x06); //
- lcd_write_register(0x5A,0x06); //
- lcd_write_register(0x5B,0x0C); //
- lcd_write_register(0x5C,0x1D); //
- lcd_write_register(0x5D,0xCC); //
- //Power Voltage Setting
- lcd_write_register(0x1B,0x1B); //VRH=4.65V
- lcd_write_register(0x1A,0x01); //BT (VGH~15V,VGL~-10V,DDVDH~5V)
- lcd_write_register(0x24,0x2F); //VMH(VCOM High voltage ~3.2V)
- lcd_write_register(0x25,0x57); //VML(VCOM Low voltage -1.2V)
- //****VCOM offset**///
- lcd_write_register(0x23,0x88); //for Flicker adjust //can reload from OTP
- //Power on Setting
- lcd_write_register(0x18,0x34); //I/P_RADJ,N/P_RADJ, Normal mode 60Hz
- lcd_write_register(0x19,0x01); //OSC_EN='1', start Osc
- lcd_write_register(0x01,0x00); //DP_STB='0', out deep sleep
- lcd_write_register(0x1F,0x88);// GAS=1, VOMG=00, PON=0, DK=1, XDK=0, DVDH_TRI=0, STB=0
- delay_ms(5);
- lcd_write_register(0x1F,0x80);// GAS=1, VOMG=00, PON=0, DK=0, XDK=0, DVDH_TRI=0, STB=0
- delay_ms(5);
- lcd_write_register(0x1F,0x90);// GAS=1, VOMG=00, PON=1, DK=0, XDK=0, DVDH_TRI=0, STB=0
- delay_ms(5);
- lcd_write_register(0x1F,0xD0);// GAS=1, VOMG=10, PON=1, DK=0, XDK=0, DDVDH_TRI=0, STB=0
- delay_ms(5);
- //262k/65k color selection
- lcd_write_register(0x17,0x05); //default 0x06 262k color // 0x05 65k color
- //SET PANEL
- lcd_write_register(0x36,0x00); //SS_P, GS_P,REV_P,BGR_P
- //Display ON Setting
- lcd_write_register(0x28,0x38); //GON=1, DTE=1, D=1000
- delay_ms(40);
- lcd_write_register(0x28,0x3F); //GON=1, DTE=1, D=1100
- lcd_write_register(0x16,0x18);
- //Set GRAM Area
- lcd_write_register(0x02,0x00);
- lcd_write_register(0x03,0x00); //Column Start
- lcd_write_register(0x04,0x00);
- lcd_write_register(0x05,0xEF); //Column End
- lcd_write_register(0x06,0x00);
- lcd_write_register(0x07,0x00); //Row Start
- lcd_write_register(0x08,0x01);
- lcd_write_register(0x09,0x3F); //Row End
-
- lcd_clear_screen(WHITE);
- //lcd_clear_screen(RED);
- }
接下来,我们配置SD卡的驱动程序:
SD卡读写一样调用的SPI1的读写函数:
- #define __SD_WRITE_BYTE(__DATA) SPI1ReadWriteByte(__DATA)
SD开的CS端配置,其中触摸芯片XPT2046也挂在这个SPI上面,本例我们先不要,但是定义它的CS引脚,让它处于不选通状态:
- void SD_port_init(void)
- {
- GPIO_InitType GPIO_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOB, ENABLE);
-
- GPIO_StructInit(&GPIO_InitStructure);
- //PB4 PB5
- GPIO_InitStructure.GPIO_Pins = SD_CS_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Pins = XPT2046_CS_PIN ;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_PP;
- //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- __SD_CS_SET();
- __XPT2046_CS_SET();
- }
SD其他操作函数:
- //data: data to be written to sd card.
- //return: data read from sd card.
- uint8_t SD_SPI_ReadWriteByte(uint8_t data)
- {
- return __SD_WRITE_BYTE(data);
- }
- //set spi in low speed mode.
- void SD_SPI_SpeedLow(void)
- {
- SPI1->CTRL1&=0XFFC7;
- SPI1->CTRL1|=SPI_MCLKP_256;
- SPI_Enable(SPI1, ENABLE);
- }
- //set spi in high speed mode.
- void SD_SPI_SpeedHigh(void)
- {
- SPI1->CTRL1&=0XFFC7;
- SPI1->CTRL1|=SPI_MCLKP_32;
- SPI_Enable(SPI1, ENABLE);
- }
- //released spi bus
- void SD_DisSelect(void)
- {
- __SD_CS_SET();
- SD_SPI_ReadWriteByte(0xff);//providing extra 8 clocks
- }
- //pick sd card and waiting until until it's ready
- //return: 0: succed 1: failure
- uint8_t SD_Select(void)
- {
- __SD_CS_CLR();
- if(SD_WaitReady()==0)return 0;
- SD_DisSelect();
- return 1;
- }
- //waiting for sd card until it's ready
- uint8_t SD_WaitReady(void)
- {
- uint32_t t=0;
- do
- {
- if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;
- t++;
- }while(t<0XFFFFFF);
- return 1;
- }
- //waiting for response from sd card.
- //Response: expect from sd card.
- //return: succeed for 0, fail for other else
- //return: 0 for success, other for failure.
- uint8_t SD_GetResponse(uint8_t Response)
- {
- uint16_t Count=0xFFFF;
- while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;
- if (Count==0)return MSD_RESPONSE_FAILURE;
- else return MSD_RESPONSE_NO_ERROR;
- }
- //read a buffer from sd card.
- //*buf: pointer to a buffer.
- //len: length of the buffer.
- //return: 0 for success, other for failure.
- uint8_t SD_RecvData(uint8_t*buf,uint16_t len)
- {
- if(SD_GetResponse(0xFE))return 1;//waiting for start command send back from sd card.
- while(len--)//receiving data...
- {
- *buf=__SD_WRITE_BYTE(0xFF);
- buf++;
- }
- //send 2 dummy write (dummy CRC)
- SD_SPI_ReadWriteByte(0xFF);
- SD_SPI_ReadWriteByte(0xFF);
- return 0;
- }
- //write a buffer containing 512 bytes to sd card.
- //buf: data buffer
- //cmd: command
- //return: 0 for success, other for failure.
- uint8_t SD_SendBlock(uint8_t*buf,uint8_t cmd)
- {
- uint16_t t;
- if(SD_WaitReady())return 1;
- SD_SPI_ReadWriteByte(cmd);
- if(cmd!=0XFD)
- {
- for(t=0;t<512;t++)__SD_WRITE_BYTE(buf[t]);
- SD_SPI_ReadWriteByte(0xFF);//ignoring CRC
- SD_SPI_ReadWriteByte(0xFF);
- t=SD_SPI_ReadWriteByte(0xFF);
- if((t&0x1F)!=0x05)return 2;
- }
- return 0;
- }
- //send a command to sd card
- //cmd:command
- //arg: parameter
- //crc: crc
- //return: response sent back from sd card.
- uint8_t SD_SendCmd(uint8_t cmd, uint32_t arg, uint8_t crc)
- {
- uint8_t r1;
- uint8_t Retry=0;
- SD_DisSelect();
- if(SD_Select())return 0XFF;
- SD_SPI_ReadWriteByte(cmd | 0x40);
- SD_SPI_ReadWriteByte(arg >> 24);
- SD_SPI_ReadWriteByte(arg >> 16);
- SD_SPI_ReadWriteByte(arg >> 8);
- SD_SPI_ReadWriteByte(arg);
- SD_SPI_ReadWriteByte(crc);
- if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff); //Skip a stuff byte when stop reading
- Retry=0X1F;
- do
- {
- r1=SD_SPI_ReadWriteByte(0xFF);
- }while((r1&0X80) && Retry--);
- return r1;
- }
- //obtain CID including manufacturer informationfrom sd card
- //*cid_dat: pointer to the buffer storing CID, at least 16 bytes.
- //return: 0 no error 1 error
- uint8_t SD_GetCID(uint8_t *cid_data)
- {
- uint8_t r1;
- r1=SD_SendCmd(CMD10,0,0x01);
- if(r1==0x00)
- {
- r1=SD_RecvData(cid_data,16);
- }
- SD_DisSelect();
- if(r1)return 1;
- else return 0;
- }
- //obtain CSD including storage and speed.
- //*csd_data : pointer to the buffer storing CSD, at least 16 bytes.
- //return: 0 no error 1 error
- uint8_t SD_GetCSD(uint8_t *csd_data)
- {
- uint8_t r1;
- r1=SD_SendCmd(CMD9,0,0x01);//发CMD9命令,读CSD send CMD9 in order to get CSD
- if(r1==0)
- {
- r1=SD_RecvData(csd_data, 16);
- }
- SD_DisSelect();
- if(r1)return 1;
- else return 0;
- }
- //obtian the totals of sectors of sd card.
- //return: 0 error, other else for storage of sd card.
- //numbers of bytes of each sector must be 512, otherwise fail to initialization.
- uint32_t SD_GetSectorCount(void)
- {
- uint8_t csd[16];
- uint32_t Capacity;
- uint8_t n;
- uint16_t csize;
-
- if(SD_GetCSD(csd)!=0) return 0;
- //calculation for SDHC below
- if((csd[0]&0xC0)==0x40) //V2.00
- {
- csize = csd[9] + ((uint16_t)csd[8] << 8) + 1;
- Capacity = (uint32_t)csize << 10; //totals of sectors
- }else//V1.XX
- {
- n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
- csize = (csd[8] >> 6) + ((uint16_t)csd[7] << 2) + ((uint16_t)(csd[6] & 3) << 10) + 1;
- Capacity= (uint32_t)csize << (n - 9);
- }
- return Capacity;
- }
- //initialize sd card
- uint8_t SD_Initialize(void)
- {
- uint8_t r1;
- uint16_t retry;
- uint8_t buf[4];
- uint16_t i;
-
- __SD_CS_SET();
- SD_SPI_SpeedLow();
- for(i=0;i<10;i++)SD_SPI_ReadWriteByte(0XFF);
- retry=20;
- do
- {
- r1=SD_SendCmd(CMD0,0,0x95);//enter to idle state
- }while((r1!=0X01) && retry--);
- SD_Type=0;
-
- if(r1==0X01)
- {
- if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
- {
- for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF); //Get trailing return value of R7 resp
- if(buf[2]==0X01&&buf[3]==0XAA)//is it support of 2.7~3.6V
- {
- retry=0XFFFE;
- do
- {
- SD_SendCmd(CMD55,0,0X01);
- r1=SD_SendCmd(CMD41,0x40000000,0X01);
- }while(r1&&retry--);
- if(retry&&SD_SendCmd(CMD58,0,0X01)==0) //start to identify the SD2.0 version of sd card.
- {
- for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//get OCR
- if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC; //check CCS
- else SD_Type=SD_TYPE_V2;
- }
- }
- }else//SD V1.x/ MMC V3
- {
- SD_SendCmd(CMD55,0,0X01);
- r1=SD_SendCmd(CMD41,0,0X01);
- if(r1<=1)
- {
- SD_Type=SD_TYPE_V1;
- retry=0XFFFE;
- do //exit idle state
- {
- SD_SendCmd(CMD55,0,0X01);
- r1=SD_SendCmd(CMD41,0,0X01);
- }while(r1&&retry--);
- }else
- {
- SD_Type=SD_TYPE_MMC;//MMC V3
- retry=0XFFFE;
- do
- {
- r1=SD_SendCmd(CMD1,0,0X01);
- }while(r1&&retry--);
- }
- if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR;
- }
- }
- SD_DisSelect();
- SD_SPI_SpeedHigh();
- if(SD_Type)return 0;
- else if(r1)return r1;
- return 0xaa;
- }
- //read SD card
- //buf: data buffer
- //sector: sector
- //cnt: totals of sectors]
- //return: 0 ok, other for failure
- uint8_t SD_ReadDisk(uint8_t*buf,uint32_t sector,uint8_t cnt)
- {
- uint8_t r1;
- if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;
- if(cnt==1)
- {
- r1=SD_SendCmd(CMD17,sector,0X01);
- if(r1==0)
- {
- r1=SD_RecvData(buf,512);
- }
- }else
- {
- r1=SD_SendCmd(CMD18,sector,0X01);
- do
- {
- r1=SD_RecvData(buf,512);
- buf+=512;
- }while(--cnt && r1==0);
- SD_SendCmd(CMD12,0,0X01);
- }
- SD_DisSelect();
- return r1;//
- }
- //write sd card
- //buf: data buffer
- //sector: start sector
- //cnt: totals of sectors]
- //return: 0 ok, other for failure
- uint8_t SD_WriteDisk(uint8_t*buf,uint32_t sector,uint8_t cnt)
- {
- uint8_t r1;
- if(SD_Type!=SD_TYPE_V2HC)sector *= 512;
- if(cnt==1)
- {
- r1=SD_SendCmd(CMD24,sector,0X01);
- if(r1==0)
- {
- r1=SD_SendBlock(buf,0xFE);
- }
- }else
- {
- if(SD_Type!=SD_TYPE_MMC)
- {
- SD_SendCmd(CMD55,0,0X01);
- SD_SendCmd(CMD23,cnt,0X01);
- }
- r1=SD_SendCmd(CMD25,sector,0X01);
- if(r1==0)
- {
- do
- {
- r1=SD_SendBlock(buf,0xFC);
- buf+=512;
- }while(--cnt && r1==0);
- r1=SD_SendBlock(0,0xFD);
- }
- }
- SD_DisSelect();
- return r1;
- }
下面我们开始移植FATFS,这个主要就是diskio和ff的文件,这里也加载了FATFS常见操作的fatfs_storage文件。
主要修改的就是diskio文件,让我们本例程中的SD具体实现函数来替代FATFS里面的底层操作函数,当然也可在ff_config
头文件里面精简FATFS系统:
- /*-----------------------------------------------------------------------*/
- /* Inidialize a Drive */
- #define SD_CARD 0 //SD卡,卷标为0
- #define FLASH_SECTOR_SIZE 512
- //初始化磁盘
- DSTATUS disk_initialize (
- BYTE drv /* Physical drive nmuber (0..) */
- )
- {
- uint8_t res=0;
- switch(drv)
- {
- case SD_CARD://SD卡
- res = SD_Initialize();//SD_Initialize()
- if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
- {
- SD_SPI_SpeedLow();
- SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
- SD_SPI_SpeedHigh();
- }
- break;
- default:
- res=1;
- }
- if(res)return STA_NOINIT;
- else return 0; //初始化成功
- }
- //获得磁盘状态
- DSTATUS disk_status (
- BYTE drv /* Physical drive nmuber (0..) */
- )
- {
- return 0;
- }
- //读扇区
- //drv:磁盘编号0~9
- //*buff:数据接收缓冲首地址
- //sector:扇区地址
- //count:需要读取的扇区数
- DRESULT disk_read (
- BYTE drv, /* Physical drive nmuber (0..) */
- BYTE *buff, /* Data buffer to store read data */
- DWORD sector, /* Sector address (LBA) */
- BYTE count /* Number of sectors to read (1..255) */
- )
- {
- uint8_t res=0;
- if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
- switch(drv)
- {
- case SD_CARD://SD卡
- res=SD_ReadDisk(buff,sector,count);
- if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
- {
- SD_SPI_SpeedLow();
- SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
- SD_SPI_SpeedHigh();
- }
- break;
- default:
- res=1;
- }
- //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
- if(res==0x00)return RES_OK;
- else return RES_ERROR;
- }
- //写扇区
- //drv:磁盘编号0~9
- //*buff:发送数据首地址
- //sector:扇区地址
- //count:需要写入的扇区数
- #if _READONLY == 0
- DRESULT disk_write (
- BYTE drv, /* Physical drive nmuber (0..) */
- const BYTE *buff, /* Data to be written */
- DWORD sector, /* Sector address (LBA) */
- BYTE count /* Number of sectors to write (1..255) */
- )
- {
- uint8_t res=0;
- if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
- switch(drv)
- {
- case SD_CARD://SD卡
- res=SD_WriteDisk((uint8_t*)buff,sector,count);
- break;
- default:
- res=1;
- }
- //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
- if(res == 0x00)return RES_OK;
- else return RES_ERROR;
- }
- #endif /* _READONLY */
- //其他表参数的获得
- //drv:磁盘编号0~9
- //ctrl:控制代码
- //*buff:发送/接收缓冲区指针
- DRESULT disk_ioctl (
- BYTE drv, /* Physical drive nmuber (0..) */
- BYTE ctrl, /* Control code */
- void *buff /* Buffer to send/receive control data */
- )
- {
- DRESULT res;
- if(drv==SD_CARD)//SD卡
- {
- switch(ctrl)
- {
- case CTRL_SYNC:
- __SD_CS_CLR();
- if(SD_WaitReady()==0)res = RES_OK;
- else res = RES_ERROR;
- __SD_CS_SET();
- break;
- case GET_SECTOR_SIZE:
- *(WORD*)buff = 512;
- res = RES_OK;
- break;
- case GET_BLOCK_SIZE:
- *(WORD*)buff = 8;
- res = RES_OK;
- break;
- case GET_SECTOR_COUNT:
- *(DWORD*)buff = SD_GetSectorCount();
- res = RES_OK;
- break;
- default:
- res = RES_PARERR;
- break;
- }
- }else res=RES_ERROR;//其他的不支持
- return res;
- }
- /*-----------------------------------------------------------------------*/
- /* User defined function to give a current time to fatfs module */
- /* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
- /* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
- DWORD get_fattime (void)
- {
- return 0;
- }
-
其他不予多说,在main文件里面添加2个函数,一个是SD挂载FATFS,一个是轮流显示SD卡根目录里面的BMP:
- char* pDirectoryFiles[MAX_BMP_FILES];
- FATFS microSDFatFs;
- uint8_t str[20];
- void SDCard_Config(void)
- {
- uint32_t counter = 0;
-
- /* Check the mounted device */
- if(f_mount(µSDFatFs, (TCHAR const*)"/", 0) != FR_OK)
- {
- lcd_display_string(0, 16, "FATFS_NOT_MOUNTED", 16, RED);
- }
- else
- {
- /* Initialize the Directory Files pointers (heap) */
- for (counter = 0; counter < MAX_BMP_FILES; counter++)
- {
- pDirectoryFiles[counter] = malloc(11);
- }
- }
- }
- static void Display_Images(void)
- {
- uint32_t bmplen = 0x00;
- uint32_t checkstatus = 0x00;
- uint32_t filesnumbers = 0x00;
- uint32_t bmpcounter = 0x00;
- DIR directory;
- FRESULT res;
-
- /* Open directory */
- res= f_opendir(&directory, "/");
- if((res != FR_OK))
- {
- if(res == FR_NO_FILESYSTEM)
- {
- /* Display message: SD card not FAT formated */
- lcd_display_string(0, 32, "SD_CARD_NOT_FORMATTED", 16, RED);
-
- }
- else
- {
- /* Display message: Fail to open directory */
- lcd_display_string(0, 48, "SD_CARD_OPEN_FAIL", 16, RED);
- }
- }
-
- /* Get number of bitmap files */
- filesnumbers = Storage_GetDirectoryBitmapFiles ("/", pDirectoryFiles);
- /* Set bitmap counter to display first image */
- bmpcounter = 1;
-
- while (1)
- {
- sprintf((char*)str, "%-11.11s", pDirectoryFiles[bmpcounter -1]);
-
- checkstatus = Storage_CheckBitmapFile((const char*)str, &bmplen);
-
- if(checkstatus == 0)
- {
- /* Format the string */
- Storage_OpenReadFile(0, 0, (const char*)str);
- }
- else if (checkstatus == 1)
- {
- /* Display message: SD card does not exist */
- lcd_display_string(0, 64, "SD_CARD_NOT_FOUND", 16, RED);
- }
- else
- {
- /* Display message: File not supported */
- lcd_display_string(0, 80, "SD_CARD_FILE_NOT_SUPPORTED", 16, RED);
- }
-
- bmpcounter ++;
- if(bmpcounter > filesnumbers)
- {
- bmpcounter = 1;
- }
-
- delay_ms(1000);
- // delay_ms(1000);
- // delay_ms(1000);
- }
- }
最终main里面添加:
- int main(void)
- {
- /*!< At this stage the microcontroller clock setting is already configured,
- this is done through SystemInit() function which is called from startup
- file (startup_at32f403_xx.s) before to branch to application main.
- To reconfigure the default setting of SystemInit() function, refer to
- system_at32f4xx.c file
- */
-
-
- /* Config LED */
- AT32_Board_Init();
- /* SPIy Config -------------------------------------------------------------*/
- SPI1_Init();
- lcd_port_init();
- lcd_init();
-
- SD_port_init();
- SDCard_Config();
-
-
- lcd_draw_rect(30, 40, 150, 100, RED);
- lcd_draw_circle(120, 160, 50, BLUE);
- lcd_draw_line(30, 40, 180, 140, RED);
- lcd_draw_line(30, 220, 210, 240, RED);
- lcd_draw_line(30, 220, 120, 280, RED);
- lcd_draw_line(120, 280, 210, 240, RED);
- lcd_clear_screen(RED);
- Delay_ms(300);
- lcd_clear_screen(BLUE);
- Delay_ms(300);
- lcd_clear_screen(YELLOW);
- Delay_ms(300);
- lcd_clear_screen(BLACK);
- Delay_ms(300);
- lcd_clear_screen(GRAY);
- Delay_ms(300);
- lcd_clear_screen(GREEN);
- Delay_ms(300);
- lcd_clear_screen(WHITE);
- Delay_ms(300);
- lcd_display_string(60, 120, (const uint8_t *)"Hello, world !", FONT_1608, BLUE);
- lcd_display_string(30, 152, (const uint8_t *)"2.8' TFT Touch Shield", FONT_1608, RED);
- lcd_display_string(30, 152+32, (const uint8_t *)"T want fly high !", FONT_1608, GREEN);
- while (1)
- {
- // AT32_LEDn_Toggle(LED2);
- // AT32_LEDn_Toggle(LED3);
- // Delay_ms(300);
- Display_Images();
-
-
- }
- }
编译,下载,查看:
代码(有需要的自取):
SPI_LCD _FATFS_BMP.rar
(5.74 MB, 下载次数: 38)