国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于stm32F103的座面聲控臺(tái)燈

這篇具有很好參考價(jià)值的文章主要介紹了基于stm32F103的座面聲控臺(tái)燈。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1.基本內(nèi)容:

????????設(shè)計(jì)一個(gè)放置在桌面使用的臺(tái)燈,使用220v交流電供電。具備顯示屏能夠?qū)崟r(shí)顯示日期(年、月、日和星期),時(shí)間(小時(shí)、分鐘、秒)和溫度(攝氏度);能夠通過(guò)語(yǔ)音交互播報(bào)實(shí)時(shí)日期、時(shí)間或者溫度;能夠通過(guò)語(yǔ)音交互控制桌面臺(tái)燈的開(kāi)啟與關(guān)閉(或者明暗程度)。設(shè)計(jì)符合安全規(guī)范,符合日常家居使用習(xí)慣,操作簡(jiǎn)便,符合人性化需求。

2.演示視頻

桌面指針式時(shí)鐘與語(yǔ)音臺(tái)燈設(shè)計(jì)

3.設(shè)計(jì)準(zhǔn)備

????????LD3320語(yǔ)音識(shí)別模塊、SYN6288語(yǔ)音合成模塊、DHT11溫濕度傳感器模塊+SL-Link下載器、STM32F103VET6、杜邦線(xiàn)、ILI9341液晶屏(野火stm32f103可一起購(gòu)買(mǎi))。

4.代碼講解

syn6288.c

#include "syn6288.h"
#include "stdarg.h"
 
xSYN6288_TypeDef  xSYN6288;                // 全局變量結(jié)構(gòu)體
 
static void delay_ms(uint32_t ms)          // 簡(jiǎn)單的延時(shí)函數(shù)
{
	 uint32_t i = 0;
    ms = ms * 11993;                       
    for (; i < ms; i++);    
}
 
 
//Music:選擇背景音樂(lè)。0:無(wú)背景音樂(lè),1~15:選擇背景音樂(lè)
// SYN6288_SendFrameInfo(0, "[v10][m1][t5]結(jié)算金額 為32.8元");
// 參數(shù): 0~15  :  背景音樂(lè),0_無(wú)背景音樂(lè),1~15_背景音樂(lè)可選
//       [V0~16]:  文本朗讀音量,0_最小,16_最大
//       [m0~16]:  背景音樂(lè)音量,0_最小,16_最大
//       [t0~5]:   朗讀語(yǔ)速,0_最慢,5_最快
//       其它不常用功能請(qǐng)參考數(shù)據(jù)手冊(cè)
static void SYN6288_SendFrameInfo(uint8_t Music, uint8_t *HZdata)
{
    /****************需要發(fā)送的文本**********************************/
    unsigned  char  Frame_Info[50];
    unsigned  char  HZ_Length;
    unsigned  char  ecc  = 0;             //定義校驗(yàn)字節(jié)
    unsigned  int i = 0;
    HZ_Length = strlen((char *)HZdata);   //需要發(fā)送文本的長(zhǎng)度
 
    /*****************幀固定配置信息**************************************/
    Frame_Info[0] = 0xFD ;                //構(gòu)造幀頭FD
    Frame_Info[1] = 0x00 ;                //構(gòu)造數(shù)據(jù)區(qū)長(zhǎng)度的高字節(jié)
    Frame_Info[2] = HZ_Length + 3;        //構(gòu)造數(shù)據(jù)區(qū)長(zhǎng)度的低字節(jié)
    Frame_Info[3] = 0x01 ;                //構(gòu)造命令字:合成播放命令
    Frame_Info[4] = 0x01 | Music << 4 ;   //構(gòu)造命令參數(shù):背景音樂(lè)設(shè)定
 
    /*******************校驗(yàn)碼計(jì)算***************************************/
    for (i = 0; i < 5; i++)               //依次發(fā)送構(gòu)造好的5個(gè)幀頭字節(jié)
        ecc = ecc ^ (Frame_Info[i]);      //對(duì)發(fā)送的字節(jié)進(jìn)行異或校驗(yàn)
 
    for (i = 0; i < HZ_Length; i++)       //依次發(fā)送待合成的文本數(shù)據(jù)
        ecc = ecc ^ (HZdata[i]);          //對(duì)發(fā)送的字節(jié)進(jìn)行異或校驗(yàn)
    /*******************發(fā)送幀信息***************************************/
    memcpy(&Frame_Info[5], HZdata, HZ_Length);
    Frame_Info[5 + HZ_Length] = ecc;
    if (xSYN6288.USARTx == USART1)   USART1_SendData(Frame_Info, 5 + HZ_Length + 1);
    if (xSYN6288.USARTx == USART2)   USART2_SendData(Frame_Info, 5 + HZ_Length + 1);
    if (xSYN6288.USARTx == USART3)   USART3_SendData(Frame_Info, 5 + HZ_Length + 1);
    if (xSYN6288.USARTx == UART4)    UART4_SendData(Frame_Info, 5 + HZ_Length + 1);
    if (xSYN6288.USARTx == UART5)    UART5_SendData(Frame_Info, 5 + HZ_Length + 1);
}
 
 
 
/***********************************************************
* 名    稱(chēng): SYN6288_Set(uint8_t *Info_data)
* 功    能: 主函數(shù) 程序入口
* 入口參數(shù): *Info_data:固定的配置信息變量
* 出口參數(shù):
* 說(shuō)    明:本函數(shù)用于配置,停止合成、暫停合成等設(shè)置 ,默認(rèn)波特率9600bps。
* 調(diào)用方法:通過(guò)調(diào)用已經(jīng)定義的相關(guān)數(shù)組進(jìn)行配置。
**********************************************************/
static void SYN6288_Set(uint8_t *Info_data)
{
    uint8_t Com_Len;
    Com_Len = strlen((char *)Info_data);
    UART5_SendData(Info_data, Com_Len);
}
 
 
/******************************************************************************
 * 函  數(shù): SYN6288_Say
 * 功  能: 輸出合成語(yǔ)音
 * 參  數(shù): 格式化參數(shù),如printf參數(shù)般一樣的用法
 * 返回值: 無(wú)
 * 示  例: SYN6288_Say("你好嗎?");
*******************************************************************************/
void SYN6288_Say(char *fmt, ...)
{
    static char  str_1[200];   // 緩存區(qū)1,模塊每次可轉(zhuǎn)換200字節(jié)
    static char  str_2[200];   // 緩存區(qū)2,模塊每次可轉(zhuǎn)換200字節(jié)
    va_list ap;
    va_start(ap, fmt);
    vsprintf(str_1, fmt, ap);
    va_end(ap);
    sprintf(str_2, "[d][V12][m15][t5]%s", str_1);  // [d]恢復(fù)默認(rèn)狀態(tài),[V12]朗讀音量0~16,[m15]背景音量0~16,[t5]語(yǔ)速0~5
    SYN6288_SendFrameInfo(0, (uint8_t *)str_2); // 無(wú)背景音樂(lè)
}
 
/******************************************************************************
 * 函  數(shù): SYN6288_Init
 * 功  能: 初始化所用串口, 模塊默認(rèn)通信波特率9600
 * 參  數(shù): 串口-USARTx
 * 返回值: 無(wú)
 * 示  例: SYN6288_Init(USART1);
*******************************************************************************/
void SYN6288_Init(USART_TypeDef *USARTx)
{
    uint16_t baudrate = 9600;      // 默認(rèn)波特率9600bps。
    delay_ms(200);                 // 上電后,稍作延時(shí),等待模塊進(jìn)入穩(wěn)定狀態(tài)
    if (USARTx == USART1)    USART1_Init(baudrate);
    if (USARTx == USART2)    USART2_Init(baudrate);
    if (USARTx == USART3)    USART3_Init(baudrate);
#ifdef STM32F10X_HD
    if (USARTx == UART4)     UART4_Init(baudrate);
    if (USARTx == UART5)     UART5_Init(baudrate);
#endif
    xSYN6288.FlagOkay = 0;         // 初始化狀態(tài)
    xSYN6288.USARTx   = USARTx;    // 記錄所用串口端口
}

DHT11.c

#include "DTH11.h"
#include "bsp_systick.h"
#include "stdio.h"
static void                           DHT11_GPIO_Config                       ( void );
static void                           DHT11_Mode_IPU                          ( void );
static void                           DHT11_Mode_Out_PP                       ( void );
static uint8_t                        DHT11_ReadByte                          ( void );


/**
  * @brief  DHT11 初始化函數(shù)
  * @param  無(wú)
  * @retval 無(wú)
  */
void DHT11_Init ( void )
{
        DHT11_GPIO_Config ();
       
        DHT11_Dout_1;               // 拉高GPIOB10
}

/*
* 函數(shù)名:DHT11_GPIO_Config
* 描述  :配置DHT11用到的I/O口
* 輸入  :無(wú)
* 輸出  :無(wú)
*/
static void DHT11_GPIO_Config ( void )
{               
        /*定義一個(gè)GPIO_InitTypeDef類(lèi)型的結(jié)構(gòu)體*/
        GPIO_InitTypeDef GPIO_InitStructure;

       
        /*開(kāi)啟DHT11_Dout_GPIO_PORT的外設(shè)時(shí)鐘*/
			DHT11_Dout_SCK_APBxClock_FUN ( DHT11_Dout_GPIO_CLK, ENABLE );       

        /*選擇要控制的DHT11_Dout_GPIO_PORT引腳*/                                                                                                                          
          GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;       

        /*設(shè)置引腳模式為通用推挽輸出*/
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

        /*設(shè)置引腳速率為50MHz */   
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

        /*調(diào)用庫(kù)函數(shù),初始化DHT11_Dout_GPIO_PORT*/
          GPIO_Init ( DHT11_Dout_GPIO_PORT, &GPIO_InitStructure );                  
       
}

/*
* 函數(shù)名:DHT11_Mode_IPU
* 描述  :使DHT11-DATA引腳變?yōu)樯侠斎肽J?* 輸入  :無(wú)
* 輸出  :無(wú)
*/
static void DHT11_Mode_IPU(void)
{
          GPIO_InitTypeDef GPIO_InitStructure;

                  /*選擇要控制的DHT11_Dout_GPIO_PORT引腳*/       
          GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;

           /*設(shè)置引腳模式為浮空輸入模式*/
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;

          /*調(diào)用庫(kù)函數(shù),初始化DHT11_Dout_GPIO_PORT*/
          GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);         
       
}

/*
* 函數(shù)名:DHT11_Mode_Out_PP
* 描述  :使DHT11-DATA引腳變?yōu)橥仆燧敵瞿J?* 輸入  :無(wú)
* 輸出  :無(wú)
*/
static void DHT11_Mode_Out_PP(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

                 /*選擇要控制的DHT11_Dout_GPIO_PORT引腳*/                                                                                                                          
          GPIO_InitStructure.GPIO_Pin = DHT11_Dout_GPIO_PIN;       

        /*設(shè)置引腳模式為通用推挽輸出*/
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

        /*設(shè)置引腳速率為50MHz */   
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

        /*調(diào)用庫(kù)函數(shù),初始化DHT11_Dout_GPIO_PORT*/
          GPIO_Init(DHT11_Dout_GPIO_PORT, &GPIO_InitStructure);                  
       
}

/*
* 從DHT11讀取一個(gè)字節(jié),MSB先行
*/
static uint8_t DHT11_ReadByte ( void )
{
        uint8_t i, temp=0;
       

        for(i=0;i<8;i++)   
        {         
                /*每bit以50us低電平標(biāo)置開(kāi)始,輪詢(xún)直到從機(jī)發(fā)出 的50us 低電平 結(jié)束*/  
                while(DHT11_Dout_IN()==Bit_RESET);

                /*DHT11 以26~28us的高電平表示“0”,以70us高電平表示“1”,
                 *通過(guò)檢測(cè) x us后的電平即可區(qū)別這兩個(gè)狀 ,x 即下面的延時(shí)
                 */
                Systick_Delay_us(40); //延時(shí)x us 這個(gè)延時(shí)需要大于數(shù)據(jù)0持續(xù)的時(shí)間即可                     

                if(DHT11_Dout_IN()==Bit_SET)/* x us后仍為高電平表示數(shù)據(jù)“1” */
                {
                        /* 等待數(shù)據(jù)1的高電平結(jié)束 */
                        while(DHT11_Dout_IN()==Bit_SET);

                        temp|=(uint8_t)(0x01<<(7-i));  //把第7-i位置1,MSB先行
                }
                else         // x us后為低電平表示數(shù)據(jù)“0”
                {                          
                        temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
                }
        }
       
        return temp;
       
}


/*
* 一次完整的數(shù)據(jù)傳輸為40bit,高位先出
* 8bit 濕度整數(shù) + 8bit 濕度小數(shù) + 8bit 溫度整數(shù) + 8bit 溫度小數(shù) + 8bit 校驗(yàn)和
*/
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{  
        /*輸出模式*/
        DHT11_Mode_Out_PP();
        /*主機(jī)拉低*/
        DHT11_Dout_0;
        /*延時(shí)18ms*/
        Systick_Delay_ms(18);

        /*總線(xiàn)拉高 主機(jī)延時(shí)30us*/
        DHT11_Dout_1;

        Systick_Delay_us(30);   //延時(shí)30us

        /*主機(jī)設(shè)為輸入 判斷從機(jī)響應(yīng)信號(hào)*/
        DHT11_Mode_IPU();

        /*判斷從機(jī)是否有低電平響應(yīng)信號(hào) 如不響應(yīng)則跳出,響應(yīng)則向下運(yùn)行*/   
        if(DHT11_Dout_IN()==Bit_RESET)     
        {
                /*輪詢(xún)直到從機(jī)發(fā)出 的80us 低電平 響應(yīng)信號(hào)結(jié)束*/  
                while(DHT11_Dout_IN()==Bit_RESET);

                /*輪詢(xún)直到從機(jī)發(fā)出的 80us 高電平 標(biāo)置信號(hào)結(jié)束*/
                while(DHT11_Dout_IN()==Bit_SET);

                /*開(kāi)始接收數(shù)據(jù)*/   
                DHT11_Data->humi_int= DHT11_ReadByte();

                DHT11_Data->humi_deci= DHT11_ReadByte();

                DHT11_Data->temp_int= DHT11_ReadByte();

                DHT11_Data->temp_deci= DHT11_ReadByte();

                DHT11_Data->check_sum= DHT11_ReadByte();


                /*讀取結(jié)束,引腳改為輸出模式*/
                DHT11_Mode_Out_PP();
                /*主機(jī)拉高*/
                DHT11_Dout_1;

                /*檢查讀取的數(shù)據(jù)是否正確*/
                if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
                        return SUCCESS;
                else
                        return ERROR;
        }
       
        else
                return ERROR;
       
}


ili9341.c

/**
  ******************************************************************************
  * @file    bsp_ili9341_lcd.c
  * @version V1.0
  * @date    2013-xx-xx
  * @brief   ili9341液晶屏驅(qū)動(dòng)
  ******************************************************************************
  * @attention
  *
  * 實(shí)驗(yàn)平臺(tái):秉火 F103-指南者 STM32 開(kāi)發(fā)板 
  * 論壇    :http://www.firebbs.cn
  * 淘寶    :http://firestm32.taobao.com
  *
  ******************************************************************************
  */ 

#include "./lcd/bsp_ili9341_lcd.h"
#include "./font/fonts.h"	
#include <math.h>

//根據(jù)液晶掃描方向而變化的XY像素寬度
//調(diào)用ILI9341_GramScan函數(shù)設(shè)置方向時(shí)會(huì)自動(dòng)更改
uint16_t LCD_X_LENGTH = ILI9341_LESS_PIXEL;
uint16_t LCD_Y_LENGTH = ILI9341_MORE_PIXEL;

//液晶屏掃描模式,本變量主要用于方便選擇觸摸屏的計(jì)算參數(shù)
//參數(shù)可選值為0-7
//調(diào)用ILI9341_GramScan函數(shù)設(shè)置方向時(shí)會(huì)自動(dòng)更改
//LCD剛初始化完成時(shí)會(huì)使用本默認(rèn)值
uint8_t LCD_SCAN_MODE = 6;




/**
  * @brief  向ILI9341寫(xiě)入命令
  * @param  usCmd :要寫(xiě)入的命令(表寄存器地址)
  * @retval 無(wú)
  */	
__inline void ILI9341_Write_Cmd ( uint16_t usCmd )
{
	* ( __IO uint16_t * ) ( FSMC_Addr_ILI9341_CMD ) = usCmd;
	
}


/**
  * @brief  向ILI9341寫(xiě)入數(shù)據(jù)
  * @param  usData :要寫(xiě)入的數(shù)據(jù)
  * @retval 無(wú)
  */	
__inline void ILI9341_Write_Data ( uint16_t usData )
{
	* ( __IO uint16_t * ) ( FSMC_Addr_ILI9341_DATA ) = usData;
	
}


/**
  * @brief  從ILI9341讀取數(shù)據(jù)
  * @param  無(wú)
  * @retval 讀取到的數(shù)據(jù)
  */	
__inline uint16_t ILI9341_Read_Data ( void )
{
	return ( * ( __IO uint16_t * ) ( FSMC_Addr_ILI9341_DATA ) );
	
}


/**
  * @brief  用于 ILI9341 簡(jiǎn)單延時(shí)函數(shù)
  * @param  nCount :延時(shí)計(jì)數(shù)值
  * @retval 無(wú)
  */	
static void ILI9341_Delay ( __IO uint32_t nCount )
{
  for ( ; nCount != 0; nCount -- );
	
}


/**
  * @brief  初始化ILI9341的IO引腳
  * @param  無(wú)
  * @retval 無(wú)
  */
static void ILI9341_GPIO_Config ( void )
{
	GPIO_InitTypeDef GPIO_InitStructure;

	/* 使能FSMC對(duì)應(yīng)相應(yīng)管腳時(shí)鐘*/
	RCC_APB2PeriphClockCmd ( 	
													/*控制信號(hào)*/
													ILI9341_CS_CLK|ILI9341_DC_CLK|ILI9341_WR_CLK|
													ILI9341_RD_CLK	|ILI9341_BK_CLK|ILI9341_RST_CLK|
													/*數(shù)據(jù)信號(hào)*/
													ILI9341_D0_CLK|ILI9341_D1_CLK|	ILI9341_D2_CLK | 
													ILI9341_D3_CLK | ILI9341_D4_CLK|ILI9341_D5_CLK|
													ILI9341_D6_CLK | ILI9341_D7_CLK|ILI9341_D8_CLK|
													ILI9341_D9_CLK | ILI9341_D10_CLK|ILI9341_D11_CLK|
													ILI9341_D12_CLK | ILI9341_D13_CLK|ILI9341_D14_CLK|
													ILI9341_D15_CLK	, ENABLE );
		
	
	/* 配置FSMC相對(duì)應(yīng)的數(shù)據(jù)線(xiàn),FSMC-D0~D15 */	
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF_PP;
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D0_PIN;
	GPIO_Init ( ILI9341_D0_PORT, & GPIO_InitStructure );

	GPIO_InitStructure.GPIO_Pin = ILI9341_D1_PIN;
	GPIO_Init ( ILI9341_D1_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D2_PIN;
	GPIO_Init ( ILI9341_D2_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D3_PIN;
	GPIO_Init ( ILI9341_D3_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D4_PIN;
	GPIO_Init ( ILI9341_D4_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D5_PIN;
	GPIO_Init ( ILI9341_D5_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D6_PIN;
	GPIO_Init ( ILI9341_D6_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D7_PIN;
	GPIO_Init ( ILI9341_D7_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D8_PIN;
	GPIO_Init ( ILI9341_D8_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D9_PIN;
	GPIO_Init ( ILI9341_D9_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D10_PIN;
	GPIO_Init ( ILI9341_D10_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D11_PIN;
	GPIO_Init ( ILI9341_D11_PORT, & GPIO_InitStructure );

	GPIO_InitStructure.GPIO_Pin = ILI9341_D12_PIN;
	GPIO_Init ( ILI9341_D12_PORT, & GPIO_InitStructure );	
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D13_PIN;
	GPIO_Init ( ILI9341_D13_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D14_PIN;
	GPIO_Init ( ILI9341_D14_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D15_PIN;
	GPIO_Init ( ILI9341_D15_PORT, & GPIO_InitStructure );
	

	
	/* 配置FSMC相對(duì)應(yīng)的控制線(xiàn)
	 * FSMC_NOE   :LCD-RD
	 * FSMC_NWE   :LCD-WR
	 * FSMC_NE1   :LCD-CS
	 * FSMC_A16  	:LCD-DC
	 */
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF_PP;
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_RD_PIN; 
	GPIO_Init (ILI9341_RD_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_WR_PIN; 
	GPIO_Init (ILI9341_WR_PORT, & GPIO_InitStructure );
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_CS_PIN; 
	GPIO_Init ( ILI9341_CS_PORT, & GPIO_InitStructure );  
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_DC_PIN; 
	GPIO_Init ( ILI9341_DC_PORT, & GPIO_InitStructure );
	

  /* 配置LCD復(fù)位RST控制管腳*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_RST_PIN; 
	GPIO_Init ( ILI9341_RST_PORT, & GPIO_InitStructure );
	
	
	/* 配置LCD背光控制管腳BK*/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_BK_PIN; 
	GPIO_Init ( ILI9341_BK_PORT, & GPIO_InitStructure );
}


 /**
  * @brief  LCD  FSMC 模式配置
  * @param  無(wú)
  * @retval 無(wú)
  */
static void ILI9341_FSMC_Config ( void )
{
	FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
	FSMC_NORSRAMTimingInitTypeDef  readWriteTiming; 	
	
	/* 使能FSMC時(shí)鐘*/
	RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_FSMC, ENABLE );

	//地址建立時(shí)間(ADDSET)為1個(gè)HCLK 2/72M=28ns
	readWriteTiming.FSMC_AddressSetupTime      = 0x01;	 //地址建立時(shí)間
	//數(shù)據(jù)保持時(shí)間(DATAST)+ 1個(gè)HCLK = 5/72M=70ns	
	readWriteTiming.FSMC_DataSetupTime         = 0x04;	 //數(shù)據(jù)建立時(shí)間
	//選擇控制的模式
	//模式B,異步NOR FLASH模式,與ILI9341的8080時(shí)序匹配
	readWriteTiming.FSMC_AccessMode            = FSMC_AccessMode_B;	
	
	/*以下配置與模式B無(wú)關(guān)*/
	//地址保持時(shí)間(ADDHLD)模式A未用到
	readWriteTiming.FSMC_AddressHoldTime       = 0x00;	 //地址保持時(shí)間
	//設(shè)置總線(xiàn)轉(zhuǎn)換周期,僅用于復(fù)用模式的NOR操作
	readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
	//設(shè)置時(shí)鐘分頻,僅用于同步類(lèi)型的存儲(chǔ)器
	readWriteTiming.FSMC_CLKDivision           = 0x00;
	//數(shù)據(jù)保持時(shí)間,僅用于同步型的NOR	
	readWriteTiming.FSMC_DataLatency           = 0x00;	

	FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait		  =FSMC_AsynchronousWait_Disable;
	FSMC_NORSRAMInitStructure.FSMC_Bank                  = FSMC_Bank1_NORSRAMx;
	FSMC_NORSRAMInitStructure.FSMC_DataAddressMux        = FSMC_DataAddressMux_Disable;
	FSMC_NORSRAMInitStructure.FSMC_MemoryType            = FSMC_MemoryType_NOR;
	FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth       = FSMC_MemoryDataWidth_16b;
	FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode       = FSMC_BurstAccessMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity    = FSMC_WaitSignalPolarity_Low;
	FSMC_NORSRAMInitStructure.FSMC_WrapMode              = FSMC_WrapMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive      = FSMC_WaitSignalActive_BeforeWaitState;
	FSMC_NORSRAMInitStructure.FSMC_WriteOperation        = FSMC_WriteOperation_Enable;
	FSMC_NORSRAMInitStructure.FSMC_WaitSignal            = FSMC_WaitSignal_Disable;
	FSMC_NORSRAMInitStructure.FSMC_ExtendedMode          = FSMC_ExtendedMode_Disable;
	FSMC_NORSRAMInitStructure.FSMC_WriteBurst            = FSMC_WriteBurst_Disable;
	FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;
	FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct     = &readWriteTiming;  
	
	FSMC_NORSRAMInit ( & FSMC_NORSRAMInitStructure ); 
	
	
	/* 使能 FSMC_Bank1_NORSRAM4 */
	FSMC_NORSRAMCmd ( FSMC_Bank1_NORSRAMx, ENABLE );  
		
		
}


/**
 * @brief  初始化ILI9341寄存器
 * @param  無(wú)
 * @retval 無(wú)
 */
static void ILI9341_REG_Config ( void )
{
	/*  Power control B (CFh)  */
	DEBUG_DELAY  ();
	ILI9341_Write_Cmd ( 0xCF  );
	ILI9341_Write_Data ( 0x00  );
	ILI9341_Write_Data ( 0x81  );
	ILI9341_Write_Data ( 0x30  );
	
	/*  Power on sequence control (EDh) */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0xED );
	ILI9341_Write_Data ( 0x64 );
	ILI9341_Write_Data ( 0x03 );
	ILI9341_Write_Data ( 0x12 );
	ILI9341_Write_Data ( 0x81 );
	
	/*  Driver timing control A (E8h) */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0xE8 );
	ILI9341_Write_Data ( 0x85 );
	ILI9341_Write_Data ( 0x10 );
	ILI9341_Write_Data ( 0x78 );
	
	/*  Power control A (CBh) */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0xCB );
	ILI9341_Write_Data ( 0x39 );
	ILI9341_Write_Data ( 0x2C );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x34 );
	ILI9341_Write_Data ( 0x02 );
	
	/* Pump ratio control (F7h) */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0xF7 );
	ILI9341_Write_Data ( 0x20 );
	
	/* Driver timing control B */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0xEA );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x00 );
	
	/* Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0xB1 );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x1B );
	
	/*  Display Function Control (B6h) */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0xB6 );
	ILI9341_Write_Data ( 0x0A );
	ILI9341_Write_Data ( 0xA2 );
	
	/* Power Control 1 (C0h) */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0xC0 );
	ILI9341_Write_Data ( 0x35 );
	
	/* Power Control 2 (C1h) */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0xC1 );
	ILI9341_Write_Data ( 0x11 );
	
	/* VCOM Control 1 (C5h) */
	ILI9341_Write_Cmd ( 0xC5 );
	ILI9341_Write_Data ( 0x45 );
	ILI9341_Write_Data ( 0x45 );
	
	/*  VCOM Control 2 (C7h)  */
	ILI9341_Write_Cmd ( 0xC7 );
	ILI9341_Write_Data ( 0xA2 );
	
	/* Enable 3G (F2h) */
	ILI9341_Write_Cmd ( 0xF2 );
	ILI9341_Write_Data ( 0x00 );
	
	/* Gamma Set (26h) */
	ILI9341_Write_Cmd ( 0x26 );
	ILI9341_Write_Data ( 0x01 );
	DEBUG_DELAY ();
	
	/* Positive Gamma Correction */
	ILI9341_Write_Cmd ( 0xE0 ); //Set Gamma
	ILI9341_Write_Data ( 0x0F );
	ILI9341_Write_Data ( 0x26 );
	ILI9341_Write_Data ( 0x24 );
	ILI9341_Write_Data ( 0x0B );
	ILI9341_Write_Data ( 0x0E );
	ILI9341_Write_Data ( 0x09 );
	ILI9341_Write_Data ( 0x54 );
	ILI9341_Write_Data ( 0xA8 );
	ILI9341_Write_Data ( 0x46 );
	ILI9341_Write_Data ( 0x0C );
	ILI9341_Write_Data ( 0x17 );
	ILI9341_Write_Data ( 0x09 );
	ILI9341_Write_Data ( 0x0F );
	ILI9341_Write_Data ( 0x07 );
	ILI9341_Write_Data ( 0x00 );
	
	/* Negative Gamma Correction (E1h) */
	ILI9341_Write_Cmd ( 0XE1 ); //Set Gamma
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x19 );
	ILI9341_Write_Data ( 0x1B );
	ILI9341_Write_Data ( 0x04 );
	ILI9341_Write_Data ( 0x10 );
	ILI9341_Write_Data ( 0x07 );
	ILI9341_Write_Data ( 0x2A );
	ILI9341_Write_Data ( 0x47 );
	ILI9341_Write_Data ( 0x39 );
	ILI9341_Write_Data ( 0x03 );
	ILI9341_Write_Data ( 0x06 );
	ILI9341_Write_Data ( 0x06 );
	ILI9341_Write_Data ( 0x30 );
	ILI9341_Write_Data ( 0x38 );
	ILI9341_Write_Data ( 0x0F );
	
	/* memory access control set */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0x36 ); 	
	ILI9341_Write_Data ( 0xC8 );    /*豎屏  左上角到 (起點(diǎn))到右下角 (終點(diǎn))掃描方式*/
	DEBUG_DELAY ();
	
	/* column address control set */
	ILI9341_Write_Cmd ( CMD_SetCoordinateX ); 
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0xEF );
	
	/* page address control set */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( CMD_SetCoordinateY ); 
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x01 );
	ILI9341_Write_Data ( 0x3F );
	
	/*  Pixel Format Set (3Ah)  */
	DEBUG_DELAY ();
	ILI9341_Write_Cmd ( 0x3a ); 
	ILI9341_Write_Data ( 0x55 );
	
	/* Sleep Out (11h)  */
	ILI9341_Write_Cmd ( 0x11 );	
	ILI9341_Delay ( 0xAFFf<<2 );
	DEBUG_DELAY ();
	
	/* Display ON (29h) */
	ILI9341_Write_Cmd ( 0x29 ); 
	
	
}


/**
 * @brief  ILI9341初始化函數(shù),如果要用到lcd,一定要調(diào)用這個(gè)函數(shù)
 * @param  無(wú)
 * @retval 無(wú)
 */
void ILI9341_Init ( void )
{
	ILI9341_GPIO_Config ();
	ILI9341_FSMC_Config ();
	
	ILI9341_BackLed_Control ( ENABLE );      //點(diǎn)亮LCD背光燈
	ILI9341_Rst ();
	ILI9341_REG_Config ();
	
	//設(shè)置默認(rèn)掃描方向,其中 6 模式為大部分液晶例程的默認(rèn)顯示方向  
	ILI9341_GramScan(LCD_SCAN_MODE);
}


/**
 * @brief  ILI9341背光LED控制
 * @param  enumState :決定是否使能背光LED
  *   該參數(shù)為以下值之一:
  *     @arg ENABLE :使能背光LED
  *     @arg DISABLE :禁用背光LED
 * @retval 無(wú)
 */
void ILI9341_BackLed_Control ( FunctionalState enumState )
{
	if ( enumState )
		GPIO_ResetBits ( ILI9341_BK_PORT, ILI9341_BK_PIN );	
	else
		GPIO_SetBits ( ILI9341_BK_PORT, ILI9341_BK_PIN );
		
}



/**
 * @brief  ILI9341 軟件復(fù)位
 * @param  無(wú)
 * @retval 無(wú)
 */
void ILI9341_Rst ( void )
{			
	GPIO_ResetBits ( ILI9341_RST_PORT, ILI9341_RST_PIN );	 //低電平復(fù)位

	ILI9341_Delay ( 0xAFF ); 					   

	GPIO_SetBits ( ILI9341_RST_PORT, ILI9341_RST_PIN );		 	 

	ILI9341_Delay ( 0xAFF ); 	
	
}




/**
 * @brief  設(shè)置ILI9341的GRAM的掃描方向 
 * @param  ucOption :選擇GRAM的掃描方向 
 *     @arg 0-7 :參數(shù)可選值為0-7這八個(gè)方向
 *
 *	?。?!其中0、3、5、6 模式適合從左至右顯示文字,
 *				不推薦使用其它模式顯示文字	其它模式顯示文字會(huì)有鏡像效果			
 *		
 *	其中0、2、4、6 模式的X方向像素為240,Y方向像素為320
 *	其中1、3、5、7 模式下X方向像素為320,Y方向像素為240
 *
 *	其中 6 模式為大部分液晶例程的默認(rèn)顯示方向
 *	其中 3 模式為攝像頭例程使用的方向
 *	其中 0 模式為BMP圖片顯示例程使用的方向
 *
 * @retval 無(wú)
 * @note  坐標(biāo)圖例:A表示向上,V表示向下,<表示向左,>表示向右
					X表示X軸,Y表示Y軸

------------------------------------------------------------
模式0:				.		模式1:		.	模式2:			.	模式3:					
					A		.					A		.		A					.		A									
					|		.					|		.		|					.		|							
					Y		.					X		.		Y					.		X					
					0		.					1		.		2					.		3					
	<--- X0 o		.	<----Y1	o		.		o 2X--->  .		o 3Y--->	
------------------------------------------------------------	
模式4:				.	模式5:			.	模式6:			.	模式7:					
	<--- X4 o		.	<--- Y5 o		.		o 6X--->  .		o 7Y--->	
					4		.					5		.		6					.		7	
					Y		.					X		.		Y					.		X						
					|		.					|		.		|					.		|							
					V		.					V		.		V					.		V		
---------------------------------------------------------				
											 LCD屏示例
								|-----------------|
								|			秉火Logo		|
								|									|
								|									|
								|									|
								|									|
								|									|
								|									|
								|									|
								|									|
								|-----------------|
								屏幕正面(寬240,高320)

 *******************************************************/
void ILI9341_GramScan ( uint8_t ucOption )
{	
	//參數(shù)檢查,只可輸入0-7
	if(ucOption >7 )
		return;
	
	//根據(jù)模式更新LCD_SCAN_MODE的值,主要用于觸摸屏選擇計(jì)算參數(shù)
	LCD_SCAN_MODE = ucOption;
	
	//根據(jù)模式更新XY方向的像素寬度
	if(ucOption%2 == 0)	
	{
		//0 2 4 6模式下X方向像素寬度為240,Y方向?yàn)?20
		LCD_X_LENGTH = ILI9341_LESS_PIXEL;
		LCD_Y_LENGTH =	ILI9341_MORE_PIXEL;
	}
	else				
	{
		//1 3 5 7模式下X方向像素寬度為320,Y方向?yàn)?40
		LCD_X_LENGTH = ILI9341_MORE_PIXEL;
		LCD_Y_LENGTH =	ILI9341_LESS_PIXEL; 
	}

	//0x36命令參數(shù)的高3位可用于設(shè)置GRAM掃描方向	
	ILI9341_Write_Cmd ( 0x36 ); 
	ILI9341_Write_Data ( 0x08 |(ucOption<<5));//根據(jù)ucOption的值設(shè)置LCD參數(shù),共0-7種模式
	ILI9341_Write_Cmd ( CMD_SetCoordinateX ); 
	ILI9341_Write_Data ( 0x00 );		/* x 起始坐標(biāo)高8位 */
	ILI9341_Write_Data ( 0x00 );		/* x 起始坐標(biāo)低8位 */
	ILI9341_Write_Data ( ((LCD_X_LENGTH-1)>>8)&0xFF ); /* x 結(jié)束坐標(biāo)高8位 */	
	ILI9341_Write_Data ( (LCD_X_LENGTH-1)&0xFF );				/* x 結(jié)束坐標(biāo)低8位 */

	ILI9341_Write_Cmd ( CMD_SetCoordinateY ); 
	ILI9341_Write_Data ( 0x00 );		/* y 起始坐標(biāo)高8位 */
	ILI9341_Write_Data ( 0x00 );		/* y 起始坐標(biāo)低8位 */
	ILI9341_Write_Data ( ((LCD_Y_LENGTH-1)>>8)&0xFF );	/* y 結(jié)束坐標(biāo)高8位 */	 
	ILI9341_Write_Data ( (LCD_Y_LENGTH-1)&0xFF );				/* y 結(jié)束坐標(biāo)低8位 */

	/* write gram start */
	ILI9341_Write_Cmd ( CMD_SetPixel );	
}



/**
 * @brief  在ILI9341顯示器上開(kāi)辟一個(gè)窗口
 * @param  usX :在特定掃描方向下窗口的起點(diǎn)X坐標(biāo)
 * @param  usY :在特定掃描方向下窗口的起點(diǎn)Y坐標(biāo)
 * @param  usWidth :窗口的寬度
 * @param  usHeight :窗口的高度
 * @retval 無(wú)
 */
void ILI9341_OpenWindow ( uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeight )
{	
	ILI9341_Write_Cmd ( CMD_SetCoordinateX ); 				 /* 設(shè)置X坐標(biāo) */
	ILI9341_Write_Data ( usX >> 8  );	 /* 先高8位,然后低8位 */
	ILI9341_Write_Data ( usX & 0xff  );	 /* 設(shè)置起始點(diǎn)和結(jié)束點(diǎn)*/
	ILI9341_Write_Data ( ( usX + usWidth - 1 ) >> 8  );
	ILI9341_Write_Data ( ( usX + usWidth - 1 ) & 0xff  );

	ILI9341_Write_Cmd ( CMD_SetCoordinateY ); 			     /* 設(shè)置Y坐標(biāo)*/
	ILI9341_Write_Data ( usY >> 8  );
	ILI9341_Write_Data ( usY & 0xff  );
	ILI9341_Write_Data ( ( usY + usHeight - 1 ) >> 8 );
	ILI9341_Write_Data ( ( usY + usHeight - 1) & 0xff );
	
}


/**
 * @brief  設(shè)定ILI9341的光標(biāo)坐標(biāo)
 * @param  usX :在特定掃描方向下光標(biāo)的X坐標(biāo)
 * @param  usY :在特定掃描方向下光標(biāo)的Y坐標(biāo)
 * @retval 無(wú)
 */
static void ILI9341_SetCursor ( uint16_t usX, uint16_t usY )	
{
	ILI9341_OpenWindow ( usX, usY, 1, 1 );
}


/**
 * @brief  在ILI9341顯示器上以某一顏色填充像素點(diǎn)
 * @param  ulAmout_Point :要填充顏色的像素點(diǎn)的總數(shù)目
 * @param  usColor :顏色
 * @retval 無(wú)
 */
static __inline void ILI9341_FillColor ( uint32_t ulAmout_Point, uint16_t usColor )
{
	uint32_t i = 0;
	
	
	/* memory write */
	ILI9341_Write_Cmd ( CMD_SetPixel );	
		
	for ( i = 0; i < ulAmout_Point; i ++ )
		ILI9341_Write_Data ( usColor );
		
	
}


/**
 * @brief  對(duì)ILI9341顯示器的某一窗口以某種顏色進(jìn)行清屏
 * @param  usX :在特定掃描方向下窗口的起點(diǎn)X坐標(biāo)
 * @param  usY :在特定掃描方向下窗口的起點(diǎn)Y坐標(biāo)
 * @param  usWidth :窗口的寬度
 * @param  usHeight :窗口的高度
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_Clear ( uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeight )
{
	ILI9341_OpenWindow ( usX, usY, usWidth, usHeight );

	ILI9341_FillColor ( usWidth * usHeight, CurrentBackColor );		
	
}


/**
 * @brief  對(duì)ILI9341顯示器的某一點(diǎn)以某種顏色進(jìn)行填充
 * @param  usX :在特定掃描方向下該點(diǎn)的X坐標(biāo)
 * @param  usY :在特定掃描方向下該點(diǎn)的Y坐標(biāo)
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_SetPointPixel ( uint16_t usX, uint16_t usY )	
{	
	if ( ( usX < LCD_X_LENGTH ) && ( usY < LCD_Y_LENGTH ))
  {
		ILI9341_SetCursor ( usX, usY );
		
		ILI9341_FillColor ( 1, CYAN );
	}
	
}


/**
 * @brief  對(duì)ILI9341顯示器的某一點(diǎn)以某種顏色進(jìn)行填充
 * @param  usX :在特定掃描方向下該點(diǎn)的X坐標(biāo)
 * @param  usY :在特定掃描方向下該點(diǎn)的Y坐標(biāo)
 * @param  fill:0和1選擇填充前景色或背景色
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_SetPointPixel_Fill ( uint16_t usX, uint16_t usY ,uint8_t fill)	
{	
	if ( ( usX < LCD_X_LENGTH ) && ( usY < LCD_Y_LENGTH )&& fill)
  {
		ILI9341_SetCursor ( usX, usY );
		
		ILI9341_FillColor ( 1, CurrentTextColor );
	}
	else
	{
		ILI9341_SetCursor ( usX, usY );
		
		ILI9341_FillColor ( 1, CurrentBackColor );
	}
	
}


/**
 * @brief  對(duì)ILI9341顯示器的某一點(diǎn)以某種顏色進(jìn)行填充
 * @param  usX :在特定掃描方向下該點(diǎn)的X坐標(biāo)
 * @param  usY :在特定掃描方向下該點(diǎn)的Y坐標(biāo)
 * @param  color:選擇某種顏色進(jìn)行填充
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_SetPointPixel_Color ( uint16_t usX, uint16_t usY ,uint16_t color)	
{	
	if ( ( usX < LCD_X_LENGTH ) && ( usY < LCD_Y_LENGTH ))
  {
		ILI9341_SetCursor ( usX, usY );
		
		ILI9341_FillColor ( 1, color );
	}
	
}
/**
 * @brief  讀取ILI9341 GRAN 的一個(gè)像素?cái)?shù)據(jù)
 * @param  無(wú)
 * @retval 像素?cái)?shù)據(jù)
 */
static uint16_t ILI9341_Read_PixelData ( void )	
{	
	uint16_t usR=0, usG=0, usB=0 ;

	
	ILI9341_Write_Cmd ( 0x2E );   /* 讀數(shù)據(jù) */
	
	usR = ILI9341_Read_Data (); 	/*FIRST READ OUT DUMMY DATA*/
	
	usR = ILI9341_Read_Data ();  	/*READ OUT RED DATA  */
	usB = ILI9341_Read_Data ();  	/*READ OUT BLUE DATA*/
	usG = ILI9341_Read_Data ();  	/*READ OUT GREEN DATA*/	
	
  return ( ( ( usR >> 11 ) << 11 ) | ( ( usG >> 10 ) << 5 ) | ( usB >> 11 ) );
	
}


/**
 * @brief  獲取 ILI9341 顯示器上某一個(gè)坐標(biāo)點(diǎn)的像素?cái)?shù)據(jù)
 * @param  usX :在特定掃描方向下該點(diǎn)的X坐標(biāo)
 * @param  usY :在特定掃描方向下該點(diǎn)的Y坐標(biāo)
 * @retval 像素?cái)?shù)據(jù)
 */
uint16_t ILI9341_GetPointPixel ( uint16_t usX, uint16_t usY )
{ 
	uint16_t usPixelData;

	
	ILI9341_SetCursor ( usX, usY );
	
	usPixelData = ILI9341_Read_PixelData ();
	
	return usPixelData;
	
}


/**
 * @brief  在 ILI9341 顯示器上使用 Bresenham 算法畫(huà)線(xiàn)段 
 * @param  usX1 :在特定掃描方向下線(xiàn)段的一個(gè)端點(diǎn)X坐標(biāo)
 * @param  usY1 :在特定掃描方向下線(xiàn)段的一個(gè)端點(diǎn)Y坐標(biāo)
 * @param  usX2 :在特定掃描方向下線(xiàn)段的另一個(gè)端點(diǎn)X坐標(biāo)
 * @param  usY2 :在特定掃描方向下線(xiàn)段的另一個(gè)端點(diǎn)Y坐標(biāo)
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_DrawLine ( uint16_t usX1, uint16_t usY1, uint16_t usX2, uint16_t usY2 )
{
	uint16_t us; 
	uint16_t usX_Current, usY_Current;
	
	int32_t lError_X = 0, lError_Y = 0, lDelta_X, lDelta_Y, lDistance; 
	int32_t lIncrease_X, lIncrease_Y; 	
	
	
	lDelta_X = usX2 - usX1; //計(jì)算坐標(biāo)增量 
	lDelta_Y = usY2 - usY1; 
	
	usX_Current = usX1; 
	usY_Current = usY1; 
	
	
	if ( lDelta_X > 0 ) 
		lIncrease_X = 1; //設(shè)置單步方向 
	
	else if ( lDelta_X == 0 ) 
		lIncrease_X = 0;//垂直線(xiàn) 
	
	else 
  { 
    lIncrease_X = -1;
    lDelta_X = - lDelta_X;
  } 

	
	if ( lDelta_Y > 0 )
		lIncrease_Y = 1; 
	
	else if ( lDelta_Y == 0 )
		lIncrease_Y = 0;//水平線(xiàn) 
	
	else 
  {
    lIncrease_Y = -1;
    lDelta_Y = - lDelta_Y;
  } 

	
	if (  lDelta_X > lDelta_Y )
		lDistance = lDelta_X; //選取基本增量坐標(biāo)軸 
	
	else 
		lDistance = lDelta_Y; 

	
	for ( us = 0; us <= lDistance + 1; us ++ )//畫(huà)線(xiàn)輸出 
	{  
		ILI9341_SetPointPixel ( usX_Current, usY_Current );//畫(huà)點(diǎn) 
		
		lError_X += lDelta_X ; 
		lError_Y += lDelta_Y ; 
		
		if ( lError_X > lDistance ) 
		{ 
			lError_X -= lDistance; 
			usX_Current += lIncrease_X; 
		}  
		
		if ( lError_Y > lDistance ) 
		{ 
			lError_Y -= lDistance; 
			usY_Current += lIncrease_Y; 
		} 
		
	}  
	
	
}   


/*
函數(shù)功能:任意角度畫(huà)直線(xiàn) 
參    數(shù):
	usX,usY:坐標(biāo)
	usAngle :度數(shù)
	usRadius:半徑
	usLength  :線(xiàn)段的長(zhǎng)度
	c  :顏色值 0或者1
例如:ILI9341_DrawAngleLine(60,30,45,20,20,1);//角度畫(huà)線(xiàn)
*/
void 	ILI9341_DrawAngleLine( uint32_t usX, uint32_t usY, float usAngle, uint32_t usRadius, uint32_t usLength,uint16_t color)
{
	int i;
	int x0,y0;
	double k=usAngle*(3.1415926535/180);	
	for(i=usRadius;i<usLength;i++)
	{
		x0=cos(k)*i;
		y0=sin(k)*i;
		ILI9341_SetPointPixel_Color(usX+x0,usY+y0,color);
	}
}




/*
函數(shù)功能:任意角度畫(huà)直線(xiàn) 
參    數(shù):
	usX,usY:坐標(biāo)
	usRadius :度數(shù)
	usLength :線(xiàn)段的長(zhǎng)度
	c  :顏色值 0或者1
例如:OLED_DrawAngleLine(60,30,45,20,20,1);//角度畫(huà)線(xiàn)
*/
void 	ILI9341_DrawAngleLine2( uint32_t usX, uint32_t usY,float usAngle,uint32_t usRadius,uint32_t usLength,uint8_t fill)
{
	uint32_t i;
	int x0,y0;
	double k=usAngle*(3.1415926535L/180);
   
	for(i=usRadius;i<usLength;i++)
	{
		x0=cos(k)*i;
		y0=sin(k)*i;
		ILI9341_SetPointPixel_Fill(usX+x0,usY+y0,fill);
	}
}


/**
 * @brief  在 ILI9341 顯示器上畫(huà)一個(gè)矩形
 * @param  usX_Start :在特定掃描方向下矩形的起始點(diǎn)X坐標(biāo)
 * @param  usY_Start :在特定掃描方向下矩形的起始點(diǎn)Y坐標(biāo)
 * @param  usWidth:矩形的寬度(單位:像素)
 * @param  usHeight:矩形的高度(單位:像素)
 * @param  ucFilled :選擇是否填充該矩形
  *   該參數(shù)為以下值之一:
  *     @arg 0 :空心矩形
  *     @arg 1 :實(shí)心矩形 
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_DrawRectangle ( uint16_t usX_Start, uint16_t usY_Start, uint16_t usWidth, uint16_t usHeight, uint8_t ucFilled )
{
	if ( ucFilled )
	{
		ILI9341_OpenWindow ( usX_Start, usY_Start, usWidth, usHeight );
		ILI9341_FillColor ( usWidth * usHeight ,CurrentTextColor);	
	}
	else
	{
		ILI9341_DrawLine ( usX_Start, usY_Start, usX_Start + usWidth - 1, usY_Start );
		ILI9341_DrawLine ( usX_Start, usY_Start + usHeight - 1, usX_Start + usWidth - 1, usY_Start + usHeight - 1 );
		ILI9341_DrawLine ( usX_Start, usY_Start, usX_Start, usY_Start + usHeight - 1 );
		ILI9341_DrawLine ( usX_Start + usWidth - 1, usY_Start, usX_Start + usWidth - 1, usY_Start + usHeight - 1 );		
	}

}


/**
 * @brief  在 ILI9341 顯示器上使用 Bresenham 算法畫(huà)圓
 * @param  usX_Center :在特定掃描方向下圓心的X坐標(biāo)
 * @param  usY_Center :在特定掃描方向下圓心的Y坐標(biāo)
 * @param  usRadius:圓的半徑(單位:像素)
 * @param  ucFilled :選擇是否填充該圓
  *   該參數(shù)為以下值之一:
  *     @arg 0 :空心圓
  *     @arg 1 :實(shí)心圓
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_DrawCircle ( uint16_t usX_Center, uint16_t usY_Center, uint16_t usRadius, uint8_t ucFilled )
{
	int16_t sCurrentX, sCurrentY;
	int16_t sError;
	
	
	sCurrentX = 0; sCurrentY = usRadius;	  
	
	sError = 3 - ( usRadius << 1 );     //判斷下個(gè)點(diǎn)位置的標(biāo)志
	
	
	while ( sCurrentX <= sCurrentY )
	{
		int16_t sCountY;
		
		
		if ( ucFilled ) 			
			for ( sCountY = sCurrentX; sCountY <= sCurrentY; sCountY ++ ) 
			{                      
				ILI9341_SetPointPixel ( usX_Center + sCurrentX, usY_Center + sCountY );           //1,研究對(duì)象 
				ILI9341_SetPointPixel ( usX_Center - sCurrentX, usY_Center + sCountY );           //2       
				ILI9341_SetPointPixel ( usX_Center - sCountY,   usY_Center + sCurrentX );           //3
				ILI9341_SetPointPixel ( usX_Center - sCountY,   usY_Center - sCurrentX );           //4
				ILI9341_SetPointPixel ( usX_Center - sCurrentX, usY_Center - sCountY );           //5    
				ILI9341_SetPointPixel ( usX_Center + sCurrentX, usY_Center - sCountY );           //6
				ILI9341_SetPointPixel ( usX_Center + sCountY,   usY_Center - sCurrentX );           //7 	
				ILI9341_SetPointPixel ( usX_Center + sCountY,   usY_Center + sCurrentX );           //0				
			}
		
		else
		{          
			ILI9341_SetPointPixel ( usX_Center + sCurrentX, usY_Center + sCurrentY );             //1,研究對(duì)象
			ILI9341_SetPointPixel ( usX_Center - sCurrentX, usY_Center + sCurrentY );             //2      
			ILI9341_SetPointPixel ( usX_Center - sCurrentY, usY_Center + sCurrentX );             //3
			ILI9341_SetPointPixel ( usX_Center - sCurrentY, usY_Center - sCurrentX );             //4
			ILI9341_SetPointPixel ( usX_Center - sCurrentX, usY_Center - sCurrentY );             //5       
			ILI9341_SetPointPixel ( usX_Center + sCurrentX, usY_Center - sCurrentY );             //6
			ILI9341_SetPointPixel ( usX_Center + sCurrentY, usY_Center - sCurrentX );             //7 
			ILI9341_SetPointPixel ( usX_Center + sCurrentY, usY_Center + sCurrentX );             //0
    }			
		
		
		sCurrentX ++;

		
		if ( sError < 0 ) 
			sError += 4 * sCurrentX + 6;	  
		
		else
		{
			sError += 10 + 4 * ( sCurrentX - sCurrentY );   
			sCurrentY --;
		} 	
		
		
	}
	
	
}

/**
 * @brief  在 ILI9341 顯示器上顯示一個(gè)英文字符
 * @param  usX :在特定掃描方向下字符的起始X坐標(biāo)
 * @param  usY :在特定掃描方向下該點(diǎn)的起始Y坐標(biāo)
 * @param  cChar :要顯示的英文字符
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_DispChar_EN ( uint16_t usX, uint16_t usY, const char cChar )
{
	uint8_t  byteCount, bitCount,fontLength;	
	uint16_t ucRelativePositon;
	uint8_t *Pfont;
	
	//對(duì)ascii碼表偏移(字模表不包含ASCII表的前32個(gè)非圖形符號(hào))
	ucRelativePositon = cChar - ' ';
	
	//每個(gè)字模的字節(jié)數(shù)
	fontLength = (LCD_Currentfonts->Width*LCD_Currentfonts->Height)/8;
		
	//字模首地址
	/*ascii碼表偏移值乘以每個(gè)字模的字節(jié)數(shù),求出字模的偏移位置*/
	Pfont = (uint8_t *)&LCD_Currentfonts->table[ucRelativePositon * fontLength];
	
	//設(shè)置顯示窗口
	ILI9341_OpenWindow ( usX, usY, LCD_Currentfonts->Width, LCD_Currentfonts->Height);
	
	ILI9341_Write_Cmd ( CMD_SetPixel );			

	//按字節(jié)讀取字模數(shù)據(jù)
	//由于前面直接設(shè)置了顯示窗口,顯示數(shù)據(jù)會(huì)自動(dòng)換行
	for ( byteCount = 0; byteCount < fontLength; byteCount++ )
	{
			//一位一位處理要顯示的顏色
			for ( bitCount = 0; bitCount < 8; bitCount++ )
			{
					if ( Pfont[byteCount] & (0x80>>bitCount) )
						ILI9341_Write_Data ( CurrentTextColor );			
					else
						ILI9341_Write_Data ( CurrentBackColor );
			}	
	}	
}


/**
 * @brief  在 ILI9341 顯示器上顯示一個(gè)中文字符
 * @param  usX :在特定掃描方向下字符的起始X坐標(biāo)
 * @param  usY :在特定掃描方向下字符的起始Y坐標(biāo)
 * @param  usChar :要顯示的中文字符(國(guó)標(biāo)碼)
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */ 
void ILI9341_DispChar_CH ( uint16_t usX, uint16_t usY, uint16_t usChar )
{
	uint8_t rowCount, bitCount;
	uint8_t ucBuffer [ WIDTH_CH_CHAR*HEIGHT_CH_CHAR/8 ];	
  uint16_t usTemp; 	

	//設(shè)置顯示窗口
	ILI9341_OpenWindow ( usX, usY, WIDTH_CH_CHAR, HEIGHT_CH_CHAR );
	
	ILI9341_Write_Cmd ( CMD_SetPixel );
	
	//取字模數(shù)據(jù)  
  GetGBKCode ( ucBuffer, usChar );	
	
	for ( rowCount = 0; rowCount < HEIGHT_CH_CHAR; rowCount++ )
	{
    /* 取出兩個(gè)字節(jié)的數(shù)據(jù),在lcd上即是一個(gè)漢字的一行 */
		usTemp = ucBuffer [ rowCount * 2 ];
		usTemp = ( usTemp << 8 );
		usTemp |= ucBuffer [ rowCount * 2 + 1 ];
		
		for ( bitCount = 0; bitCount < WIDTH_CH_CHAR; bitCount ++ )
		{			
			if ( usTemp & ( 0x8000 >> bitCount ) )  //高位在前 
			  ILI9341_Write_Data ( CurrentTextColor );				
			else
				ILI9341_Write_Data ( CurrentBackColor );			
		}		
	}
	
}


/**
 * @brief  在 ILI9341 顯示器上顯示英文字符串
 * @param  line :在特定掃描方向下字符串的起始Y坐標(biāo)
  *   本參數(shù)可使用宏LINE(0)、LINE(1)等方式指定文字坐標(biāo),
  *   宏LINE(x)會(huì)根據(jù)當(dāng)前選擇的字體來(lái)計(jì)算Y坐標(biāo)值。
	*		顯示中文且使用LINE宏時(shí),需要把英文字體設(shè)置成Font8x16
 * @param  pStr :要顯示的英文字符串的首地址
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_DispStringLine_EN (  uint16_t line,  char * pStr )
{
	uint16_t usX = 0;
	
	while ( * pStr != '\0' )
	{
		if ( ( usX - ILI9341_DispWindow_X_Star + LCD_Currentfonts->Width ) > LCD_X_LENGTH )
		{
			usX = ILI9341_DispWindow_X_Star;
			line += LCD_Currentfonts->Height;
		}
		
		if ( ( line - ILI9341_DispWindow_Y_Star + LCD_Currentfonts->Height ) > LCD_Y_LENGTH )
		{
			usX = ILI9341_DispWindow_X_Star;
			line = ILI9341_DispWindow_Y_Star;
		}
		
		ILI9341_DispChar_EN ( usX, line, * pStr);
		
		pStr ++;
		
		usX += LCD_Currentfonts->Width;
		
	}
	
}


/**
 * @brief  在 ILI9341 顯示器上顯示英文字符串
 * @param  usX :在特定掃描方向下字符的起始X坐標(biāo)
 * @param  usY :在特定掃描方向下字符的起始Y坐標(biāo)
 * @param  pStr :要顯示的英文字符串的首地址
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_DispString_EN ( 	uint16_t usX ,uint16_t usY,  char * pStr )
{
	while ( * pStr != '\0' )
	{
		if ( ( usX - ILI9341_DispWindow_X_Star + LCD_Currentfonts->Width ) > LCD_X_LENGTH )
		{
			usX = ILI9341_DispWindow_X_Star;
			usY += LCD_Currentfonts->Height;
		}
		
		if ( ( usY - ILI9341_DispWindow_Y_Star + LCD_Currentfonts->Height ) > LCD_Y_LENGTH )
		{
			usX = ILI9341_DispWindow_X_Star;
			usY = ILI9341_DispWindow_Y_Star;
		}
		
		ILI9341_DispChar_EN ( usX, usY, * pStr);
		
		pStr ++;
		
		usX += LCD_Currentfonts->Width;
		
	}
	
}


/**
 * @brief  在 ILI9341 顯示器上顯示英文字符串(沿Y軸方向)
 * @param  usX :在特定掃描方向下字符的起始X坐標(biāo)
 * @param  usY :在特定掃描方向下字符的起始Y坐標(biāo)
 * @param  pStr :要顯示的英文字符串的首地址
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_DispString_EN_YDir (	 uint16_t usX,uint16_t usY ,  char * pStr )
{	
	while ( * pStr != '\0' )
	{
		if ( ( usY - ILI9341_DispWindow_Y_Star + LCD_Currentfonts->Height ) >LCD_Y_LENGTH  )
		{
			usY = ILI9341_DispWindow_Y_Star;
			usX += LCD_Currentfonts->Width;
		}
		
		if ( ( usX - ILI9341_DispWindow_X_Star + LCD_Currentfonts->Width ) >  LCD_X_LENGTH)
		{
			usX = ILI9341_DispWindow_X_Star;
			usY = ILI9341_DispWindow_Y_Star;
		}
		
		ILI9341_DispChar_EN ( usX, usY, * pStr);
		
		pStr ++;
		
		usY += LCD_Currentfonts->Height;		
	}	
}


/**
 * @brief  在 ILI9341 顯示器上顯示中英文字符串
 * @param  usX :在特定掃描方向下字符的起始X坐標(biāo)
 * @param  usY :在特定掃描方向下字符的起始Y坐標(biāo)
 * @param  pStr :要顯示的字符串的首地址
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_DispString_EN_CH ( 	uint16_t usX , uint16_t usY, char * pStr )
{
	uint16_t usCh;
	
	while( * pStr != '\0' )
	{
		if ( * pStr <= 126 )	           	//英文字符
		{
			if ( ( usX - ILI9341_DispWindow_X_Star + LCD_Currentfonts->Width ) > LCD_X_LENGTH )
			{
				usX = ILI9341_DispWindow_X_Star;
				usY += LCD_Currentfonts->Height;
			}
			
			if ( ( usY - ILI9341_DispWindow_Y_Star + LCD_Currentfonts->Height ) > LCD_Y_LENGTH )
			{
				usX = ILI9341_DispWindow_X_Star;
				usY = ILI9341_DispWindow_Y_Star;
			}			
		
		  ILI9341_DispChar_EN ( usX, usY, * pStr );
			
			usX +=  LCD_Currentfonts->Width;
		
		  pStr ++;

		}
		
		else	                            //漢字字符
		{
			if ( ( usX - ILI9341_DispWindow_X_Star + WIDTH_CH_CHAR ) > LCD_X_LENGTH )
			{
				usX = ILI9341_DispWindow_X_Star;
				usY += HEIGHT_CH_CHAR;
			}
			
			if ( ( usY - ILI9341_DispWindow_Y_Star + HEIGHT_CH_CHAR ) > LCD_Y_LENGTH )
			{
				usX = ILI9341_DispWindow_X_Star;
				usY = ILI9341_DispWindow_Y_Star;
			}	
			
			usCh = * ( uint16_t * ) pStr;	
			
			usCh = ( usCh << 8 ) + ( usCh >> 8 );		

			ILI9341_DispChar_CH ( usX, usY, usCh );
			
			usX += WIDTH_CH_CHAR;
			
			pStr += 2;           //一個(gè)漢字兩個(gè)字節(jié) 
		
    }
		
  }	
} 


/**
 * @brief  在 ILI9341 顯示器上顯示中英文字符串
 * @param  line :在特定掃描方向下字符串的起始Y坐標(biāo)
  *   本參數(shù)可使用宏LINE(0)、LINE(1)等方式指定文字坐標(biāo),
  *   宏LINE(x)會(huì)根據(jù)當(dāng)前選擇的字體來(lái)計(jì)算Y坐標(biāo)值。
	*		顯示中文且使用LINE宏時(shí),需要把英文字體設(shè)置成Font8x16
 * @param  pStr :要顯示的字符串的首地址
 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函數(shù)設(shè)置顏色
 * @retval 無(wú)
 */
void ILI9341_DispStringLine_EN_CH (  uint16_t line, char * pStr )
{
	uint16_t usCh;
	uint16_t usX = 0;
	
	while( * pStr != '\0' )
	{
		if ( * pStr <= 126 )	           	//英文字符
		{
			if ( ( usX - ILI9341_DispWindow_X_Star + LCD_Currentfonts->Width ) > LCD_X_LENGTH )
			{
				usX = ILI9341_DispWindow_X_Star;
				line += LCD_Currentfonts->Height;
			}
			
			if ( ( line - ILI9341_DispWindow_Y_Star + LCD_Currentfonts->Height ) > LCD_Y_LENGTH )
			{
				usX = ILI9341_DispWindow_X_Star;
				line = ILI9341_DispWindow_Y_Star;
			}			
		
		  ILI9341_DispChar_EN ( usX, line, * pStr );
			
			usX +=  LCD_Currentfonts->Width;
		
		  pStr ++;

		}
		
		else	                            //漢字字符
		{
			if ( ( usX - ILI9341_DispWindow_X_Star + WIDTH_CH_CHAR ) > LCD_X_LENGTH )
			{
				usX = ILI9341_DispWindow_X_Star;
				line += HEIGHT_CH_CHAR;
			}
			
			if ( ( line - ILI9341_DispWindow_Y_Star + HEIGHT_CH_CHAR ) > LCD_Y_LENGTH )
			{
				usX = ILI9341_DispWindow_X_Star;
				line = ILI9341_DispWindow_Y_Star;
			}	
			
			usCh = * ( uint16_t * ) pStr;	
			
			usCh = ( usCh << 8 ) + ( usCh >> 8 );		

			ILI9341_DispChar_CH ( usX, line, usCh );
			
			usX += WIDTH_CH_CHAR;
			
			pStr += 2;           //一個(gè)漢字兩個(gè)字節(jié) 
		
    }
		
  }	
} 

/**
  * @brief  設(shè)置英文字體類(lèi)型
  * @param  fonts: 指定要選擇的字體
	*		參數(shù)為以下值之一
  * 	@arg:Font24x32;
  * 	@arg:Font16x24;
  * 	@arg:Font8x16;
  * @retval None
  */
void LCD_SetFont(sFONT *fonts)
{
  LCD_Currentfonts = fonts;
}

/**
  * @brief  獲取當(dāng)前字體類(lèi)型
  * @param  None.
  * @retval 返回當(dāng)前字體類(lèi)型
  */
sFONT *LCD_GetFont(void)
{
  return LCD_Currentfonts;
}


/**
  * @brief  設(shè)置LCD的前景(字體)及背景顏色,RGB565
  * @param  TextColor: 指定前景(字體)顏色
  * @param  BackColor: 指定背景顏色
  * @retval None
  */
void LCD_SetColors(uint16_t TextColor, uint16_t BackColor) 
{
  CurrentTextColor = TextColor; 
  CurrentBackColor = BackColor;
}

/**
  * @brief  獲取LCD的前景(字體)及背景顏色,RGB565
  * @param  TextColor: 用來(lái)存儲(chǔ)前景(字體)顏色的指針變量
  * @param  BackColor: 用來(lái)存儲(chǔ)背景顏色的指針變量
  * @retval None
  */
void LCD_GetColors(uint16_t *TextColor, uint16_t *BackColor)
{
  *TextColor = CurrentTextColor;
  *BackColor = CurrentBackColor;
}

/**
  * @brief  設(shè)置LCD的前景(字體)顏色,RGB565
  * @param  Color: 指定前景(字體)顏色 
  * @retval None
  */
void LCD_SetTextColor(uint16_t Color)
{
  CurrentTextColor = Color;
}

/**
  * @brief  設(shè)置LCD的背景顏色,RGB565
  * @param  Color: 指定背景顏色 
  * @retval None
  */
void LCD_SetBackColor(uint16_t Color)
{
  CurrentBackColor = Color;
}


/**
  * @brief  清除某行文字
  * @param  Line: 指定要?jiǎng)h除的行
  *   本參數(shù)可使用宏LINE(0)、LINE(1)等方式指定要?jiǎng)h除的行,
  *   宏LINE(x)會(huì)根據(jù)當(dāng)前選擇的字體來(lái)計(jì)算Y坐標(biāo)值,并刪除當(dāng)前字體高度的第x行。
  * @retval None
  */
void LCD_ClearLine(uint16_t Line)
{
  ILI9341_Clear(0,Line,LCD_X_LENGTH,((sFONT *)LCD_GetFont())->Height);	/* 清屏,顯示全黑 */

}



/***********************縮放字體****************************/
#define ZOOMMAXBUFF 16384
uint8_t zoomBuff[ZOOMMAXBUFF] = {0};	//用于縮放的緩存,最大支持到128*128
uint8_t zoomTempBuff[1024] = {0};

/**
 * @brief  縮放字模,縮放后的字模由1個(gè)像素點(diǎn)由8個(gè)數(shù)據(jù)位來(lái)表示
										0x01表示筆跡,0x00表示空白區(qū)
 * @param  in_width :原始字符寬度
 * @param  in_heig :原始字符高度
 * @param  out_width :縮放后的字符寬度
 * @param  out_heig:縮放后的字符高度
 * @param  in_ptr :字庫(kù)輸入指針	注意:1pixel 1bit
 * @param  out_ptr :縮放后的字符輸出指針 注意: 1pixel 8bit
 *		out_ptr實(shí)際上沒(méi)有正常輸出,改成了直接輸出到全局指針zoomBuff中
 * @param  en_cn :0為英文,1為中文
 * @retval 無(wú)
 */
void ILI9341_zoomChar(uint16_t in_width,	//原始字符寬度
									uint16_t in_heig,		//原始字符高度
									uint16_t out_width,	//縮放后的字符寬度
									uint16_t out_heig,	//縮放后的字符高度
									uint8_t *in_ptr,	//字庫(kù)輸入指針	注意:1pixel 1bit
									uint8_t *out_ptr, //縮放后的字符輸出指針 注意: 1pixel 8bit
									uint8_t en_cn)		//0為英文,1為中文	
{
	uint8_t *pts,*ots;
	//根據(jù)源字模及目標(biāo)字模大小,設(shè)定運(yùn)算比例因子,左移16是為了把浮點(diǎn)運(yùn)算轉(zhuǎn)成定點(diǎn)運(yùn)算
	unsigned int xrIntFloat_16=(in_width<<16)/out_width+1; 
  unsigned int yrIntFloat_16=(in_heig<<16)/out_heig+1;
	
	unsigned int srcy_16=0;
	unsigned int y,x;
	uint8_t *pSrcLine;
	
	uint16_t byteCount,bitCount;
	
	//檢查參數(shù)是否合法
	if(in_width >= 32) return;												//字庫(kù)不允許超過(guò)32像素
	if(in_width * in_heig == 0) return;	
	if(in_width * in_heig >= 1024 ) return; 					//限制輸入最大 32*32
	
	if(out_width * out_heig == 0) return;	
	if(out_width * out_heig >= ZOOMMAXBUFF ) return; //限制最大縮放 128*128
	pts = (uint8_t*)&zoomTempBuff;
	
	//為方便運(yùn)算,字庫(kù)的數(shù)據(jù)由1 pixel/1bit 映射到1pixel/8bit
	//0x01表示筆跡,0x00表示空白區(qū)
	if(en_cn == 0x00)//英文
	{
		//英文和中文字庫(kù)上下邊界不對(duì),可在此處調(diào)整。需要注意tempBuff防止溢出
			for(byteCount=0;byteCount<in_heig*in_width/8;byteCount++)	
			{
				for(bitCount=0;bitCount<8;bitCount++)
					{						
						//把源字模數(shù)據(jù)由位映射到字節(jié)
						//in_ptr里bitX為1,則pts里整個(gè)字節(jié)值為1
						//in_ptr里bitX為0,則pts里整個(gè)字節(jié)值為0
						*pts++ = (in_ptr[byteCount] & (0x80>>bitCount))?1:0; 
					}
			}				
	}
	else //中文
	{			
			for(byteCount=0;byteCount<in_heig*in_width/8;byteCount++)	
			{
				for(bitCount=0;bitCount<8;bitCount++)
					{						
						//把源字模數(shù)據(jù)由位映射到字節(jié)
						//in_ptr里bitX為1,則pts里整個(gè)字節(jié)值為1
						//in_ptr里bitX為0,則pts里整個(gè)字節(jié)值為0
						*pts++ = (in_ptr[byteCount] & (0x80>>bitCount))?1:0; 
					}
			}		
	}

	//zoom過(guò)程
	pts = (uint8_t*)&zoomTempBuff;	//映射后的源數(shù)據(jù)指針
	ots = (uint8_t*)&zoomBuff;	//輸出數(shù)據(jù)的指針
	for (y=0;y<out_heig;y++)	/*行遍歷*/
    {
				unsigned int srcx_16=0;
        pSrcLine=pts+in_width*(srcy_16>>16);				
        for (x=0;x<out_width;x++) /*行內(nèi)像素遍歷*/
        {
            ots[x]=pSrcLine[srcx_16>>16]; //把源字模數(shù)據(jù)復(fù)制到目標(biāo)指針中
            srcx_16+=xrIntFloat_16;			//按比例偏移源像素點(diǎn)
        }
        srcy_16+=yrIntFloat_16;				  //按比例偏移源像素點(diǎn)
        ots+=out_width;						
    }
	/*?。。】s放后的字模數(shù)據(jù)直接存儲(chǔ)到全局指針zoomBuff里了*/
	out_ptr = (uint8_t*)&zoomBuff;	//out_ptr沒(méi)有正確傳出,后面調(diào)用直接改成了全局變量指針!
	
	/*實(shí)際中如果使用out_ptr不需要下面這一句?。?!
		只是因?yàn)閛ut_ptr沒(méi)有使用,會(huì)導(dǎo)致warning。強(qiáng)迫癥*/
	out_ptr++; 
}			


/**
 * @brief  利用縮放后的字模顯示字符
 * @param  Xpos :字符顯示位置x
 * @param  Ypos :字符顯示位置y
 * @param  Font_width :字符寬度
 * @param  Font_Heig:字符高度
 * @param  c :要顯示的字模數(shù)據(jù)
 * @param  DrawModel :是否反色顯示 
 * @retval 無(wú)
 */
void ILI9341_DrawChar_Ex(uint16_t usX, //字符顯示位置x
												uint16_t usY, //字符顯示位置y
												uint16_t Font_width, //字符寬度
												uint16_t Font_Height,  //字符高度 
												uint8_t *c,						//字模數(shù)據(jù)
												uint16_t DrawModel)		//是否反色顯示
{
  uint32_t index = 0, counter = 0;

	//設(shè)置顯示窗口
	ILI9341_OpenWindow ( usX, usY, Font_width, Font_Height);
	
	ILI9341_Write_Cmd ( CMD_SetPixel );		
	
	//按字節(jié)讀取字模數(shù)據(jù)
	//由于前面直接設(shè)置了顯示窗口,顯示數(shù)據(jù)會(huì)自動(dòng)換行
	for ( index = 0; index < Font_Height; index++ )
	{
			//一位一位處理要顯示的顏色
			for ( counter = 0; counter < Font_width; counter++ )
			{
					//縮放后的字模數(shù)據(jù),以一個(gè)字節(jié)表示一個(gè)像素位
					//整個(gè)字節(jié)值為1表示該像素為筆跡
					//整個(gè)字節(jié)值為0表示該像素為背景
					if ( *c++ == DrawModel )
						ILI9341_Write_Data ( CurrentBackColor );			
					else
						ILI9341_Write_Data ( CurrentTextColor );
			}	
	}	
}


/**
 * @brief  利用縮放后的字模顯示字符串
 * @param  Xpos :字符顯示位置x
 * @param  Ypos :字符顯示位置y
 * @param  Font_width :字符寬度,英文字符在此基礎(chǔ)上/2。注意為偶數(shù)
 * @param  Font_Heig:字符高度,注意為偶數(shù)
 * @param  c :要顯示的字符串
 * @param  DrawModel :是否反色顯示 
 * @retval 無(wú)
 */
void ILI9341_DisplayStringEx(uint16_t x, 		//字符顯示位置x
														 uint16_t y, 				//字符顯示位置y
														 uint16_t Font_width,	//要顯示的字體寬度,英文字符在此基礎(chǔ)上/2。注意為偶數(shù)
														 uint16_t Font_Height,	//要顯示的字體高度,注意為偶數(shù)
														 uint8_t *ptr,					//顯示的字符內(nèi)容
														 uint16_t DrawModel)  //是否反色顯示



{
	uint16_t Charwidth = Font_width; //默認(rèn)為Font_width,英文寬度為中文寬度的一半
	uint8_t *psr;
	uint8_t Ascii;	//英文
	uint16_t usCh;  //中文
	uint8_t ucBuffer [ WIDTH_CH_CHAR*HEIGHT_CH_CHAR/8 ];	
	
	while ( *ptr != '\0')
	{
			/****處理?yè)Q行*****/
			if ( ( x - ILI9341_DispWindow_X_Star + Charwidth ) > LCD_X_LENGTH )
			{
				x = ILI9341_DispWindow_X_Star;
				y += Font_Height;
			}
			
			if ( ( y - ILI9341_DispWindow_Y_Star + Font_Height ) > LCD_Y_LENGTH )
			{
				x = ILI9341_DispWindow_X_Star;
				y = ILI9341_DispWindow_Y_Star;
			}	
			
		if(*ptr > 0x80) //如果是中文
		{			
			Charwidth = Font_width;
			usCh = * ( uint16_t * ) ptr;				
			usCh = ( usCh << 8 ) + ( usCh >> 8 );
			GetGBKCode ( ucBuffer, usCh );	//取字模數(shù)據(jù)
			//縮放字模數(shù)據(jù),源字模為16*16
			ILI9341_zoomChar(WIDTH_CH_CHAR,HEIGHT_CH_CHAR,Charwidth,Font_Height,(uint8_t *)&ucBuffer,psr,1); 
			//顯示單個(gè)字符
			ILI9341_DrawChar_Ex(x,y,Charwidth,Font_Height,(uint8_t*)&zoomBuff,DrawModel);
			x+=Charwidth;
			ptr+=2;
		}
		else
		{
				Charwidth = Font_width / 2;
				Ascii = *ptr - 32;
				//使用16*24字體縮放字模數(shù)據(jù)
				ILI9341_zoomChar(16,24,Charwidth,Font_Height,(uint8_t *)&Font16x24.table[Ascii * Font16x24.Height*Font16x24.Width/8],psr,0);
			  //顯示單個(gè)字符
				ILI9341_DrawChar_Ex(x,y,Charwidth,Font_Height,(uint8_t*)&zoomBuff,DrawModel);
				x+=Charwidth;
				ptr++;
		}
	}
}


/**
 * @brief  利用縮放后的字模顯示字符串(沿Y軸方向)
 * @param  Xpos :字符顯示位置x
 * @param  Ypos :字符顯示位置y
 * @param  Font_width :字符寬度,英文字符在此基礎(chǔ)上/2。注意為偶數(shù)
 * @param  Font_Heig:字符高度,注意為偶數(shù)
 * @param  c :要顯示的字符串
 * @param  DrawModel :是否反色顯示 
 * @retval 無(wú)
 */
void ILI9341_DisplayStringEx_YDir(uint16_t x, 		//字符顯示位置x
																		 uint16_t y, 				//字符顯示位置y
																		 uint16_t Font_width,	//要顯示的字體寬度,英文字符在此基礎(chǔ)上/2。注意為偶數(shù)
																		 uint16_t Font_Height,	//要顯示的字體高度,注意為偶數(shù)
																		 uint8_t *ptr,					//顯示的字符內(nèi)容
																		 uint16_t DrawModel)  //是否反色顯示
{
	uint16_t Charwidth = Font_width; //默認(rèn)為Font_width,英文寬度為中文寬度的一半
	uint8_t *psr;
	uint8_t Ascii;	//英文
	uint16_t usCh;  //中文
	uint8_t ucBuffer [ WIDTH_CH_CHAR*HEIGHT_CH_CHAR/8 ];	
	
	while ( *ptr != '\0')
	{			
			//統(tǒng)一使用漢字的寬高來(lái)計(jì)算換行
			if ( ( y - ILI9341_DispWindow_X_Star + Font_width ) > LCD_Y_LENGTH )
			{
				y = ILI9341_DispWindow_X_Star;
				x += Font_width;
			}
			
			if ( ( x - ILI9341_DispWindow_Y_Star + Font_Height ) > LCD_X_LENGTH )
			{
				y = ILI9341_DispWindow_X_Star;
				x = ILI9341_DispWindow_Y_Star;
			}	
			
		if(*ptr > 0x80) //如果是中文
		{			
			Charwidth = Font_width;
			usCh = * ( uint16_t * ) ptr;				
			usCh = ( usCh << 8 ) + ( usCh >> 8 );
			GetGBKCode ( ucBuffer, usCh );	//取字模數(shù)據(jù)
			//縮放字模數(shù)據(jù),源字模為16*16
			ILI9341_zoomChar(WIDTH_CH_CHAR,HEIGHT_CH_CHAR,Charwidth,Font_Height,(uint8_t *)&ucBuffer,psr,1); 
			//顯示單個(gè)字符
			ILI9341_DrawChar_Ex(x,y,Charwidth,Font_Height,(uint8_t*)&zoomBuff,DrawModel);
			y+=Font_Height;
			ptr+=2;
		}
		else
		{
				Charwidth = Font_width / 2;
				Ascii = *ptr - 32;
				//使用16*24字體縮放字模數(shù)據(jù)
				ILI9341_zoomChar(16,24,Charwidth,Font_Height,(uint8_t *)&Font16x24.table[Ascii * Font16x24.Height*Font16x24.Width/8],psr,0);
			  //顯示單個(gè)字符
				ILI9341_DrawChar_Ex(x,y,Charwidth,Font_Height,(uint8_t*)&zoomBuff,DrawModel);
				y+=Font_Height;
				ptr++;
		}
	}
}



/*********************end of file*************************/


LD3320.c/usart.c

#include "bsp_usart.h"
#include <string.h>

 /**
  * @brief  USART GPIO 配置,工作參數(shù)配置
  * @param  無(wú)
  * @retval 無(wú)
  */
void USART_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	// 打開(kāi)串口GPIO的時(shí)鐘
	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
	
	// 打開(kāi)串口外設(shè)的時(shí)鐘
	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);

	// 將USART Tx的GPIO配置為推挽復(fù)用模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

  // 將USART Rx的GPIO配置為浮空輸入模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
	
	// 配置串口的工作參數(shù)
	// 配置波特率
	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
	// 配置 針數(shù)據(jù)字長(zhǎng)
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	// 配置停止位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	// 配置校驗(yàn)位
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	// 配置硬件流控制
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	// 配置工作模式,收發(fā)一起
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	// 完成串口的初始化配置
	USART_Init(DEBUG_USARTx, &USART_InitStructure);

	// 使能串口
	USART_Cmd(DEBUG_USARTx, ENABLE);	    
}



/**
  * @brief  配置嵌套向量中斷控制器NVIC
  * @param  無(wú)
  * @retval 無(wú)
  */
static void NVIC_USART3_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;//使能中斷接收
  
  /* 嵌套向量中斷控制器組選擇 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* 配置USART為中斷源 */
  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  /* 搶斷優(yōu)先級(jí)*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 子優(yōu)先級(jí) */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中斷 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  /* 初始化配置NVIC */
  NVIC_Init(&NVIC_InitStructure);
  
}



/*
PB10   :TXD
PB11   : RXD
*/

//串口IO初始化函數(shù)
void USART3_Init(uint32_t baudrate)
{
	GPIO_InitTypeDef GPIO_InitStructure;         //IO端口的初始化
	USART_InitTypeDef USART_InitStructure;			 //串口的初始化       
	
	RCC_APB2PeriphClockCmd(Ld3320_USART_GPIO_CLK, ENABLE);  //使能IO端口的時(shí)鐘
   RCC_APB1PeriphClockCmd(Ld3320_USART_CLK, ENABLE); //使能串口的時(shí)鐘
	
	//發(fā)送
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin  = Ld3320_USART_TX_GPIO_PIN;  //發(fā)送引腳
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//接收
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin  = Ld3320_USART_RX_GPIO_PIN;  //接收引腳
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);

	USART_InitStructure.USART_BaudRate = baudrate;    //設(shè)置傳輸?shù)牟ㄌ芈?	USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //設(shè)置傳輸一幀數(shù)據(jù)的數(shù)據(jù)位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;       //一位停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;					 //無(wú)奇偶校驗(yàn)位
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  //能使接收的發(fā)送
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  //無(wú)硬件流控制
	USART_Init(Ld3320_USARTx,&USART_InitStructure);
	
	NVIC_USART3_Configuration();
	
	USART_ITConfig(Ld3320_USARTx,USART_IT_RXNE,ENABLE); //使能串口中斷
   USART_Cmd(Ld3320_USARTx,ENABLE);               //使能串口2
	
}

/*
函數(shù)名:USART3串口發(fā)送函數(shù)
功能:  發(fā)送數(shù)據(jù)
入口參數(shù):發(fā)送的字符
*/
void USART3_SendString(u8 *str)
{
		u8 index=0;
	  do
		{
					USART_SendData(USART3,str[index]);  //逐一的發(fā)送數(shù)組中的內(nèi)容
					while(USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET);  //判斷是否發(fā)送完 發(fā)完為高電平
					index++;
		}
    while(str[index] != 0);   //檢查字符串結(jié)束標(biāo)志
}


xUSATR_TypeDef  xUSART;         // 聲明為全局變量,方便記錄信息、狀態(tài)




//   USART-1   //
/
/******************************************************************************
 * 函  數(shù): vUSART1_Init
 * 功  能: 初始化USART1的GPIO、通信參數(shù)配置、中斷優(yōu)先級(jí)
 *          (8位數(shù)據(jù)、無(wú)校驗(yàn)、1個(gè)停止位)
 * 參  數(shù): uint32_t baudrate  通信波特率
 * 返回值: 無(wú)
 ******************************************************************************/
void USART1_Init(uint32_t baudrate)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    NVIC_InitTypeDef  NVIC_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    // 時(shí)鐘使能
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;                           // 使能USART1時(shí)鐘
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;                             // 使能GPIOA時(shí)鐘

    // GPIO_TX引腳配置
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;                // TX引腳工作模式:復(fù)用推挽
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // GPIO_RX引腳配置
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;                  // RX引腳工作模式:上拉輸入; 如果使用浮空輸入,引腳空置時(shí)可能產(chǎn)生誤輸入; 當(dāng)電路上為一主多從電路時(shí),可以使用復(fù)用開(kāi)漏模式
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 中斷配置
    NVIC_InitStructure .NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure .NVIC_IRQChannelPreemptionPriority = 2 ;     // 搶占優(yōu)先級(jí)
    NVIC_InitStructure .NVIC_IRQChannelSubPriority = 2;             // 子優(yōu)先級(jí)
    NVIC_InitStructure .NVIC_IRQChannelCmd = ENABLE;                // IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);

    //USART 初始化設(shè)置
    USART_DeInit(USART1);
    USART_InitStructure.USART_BaudRate   = baudrate;                // 串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;     // 字長(zhǎng)為8位數(shù)據(jù)格式
    USART_InitStructure.USART_StopBits   = USART_StopBits_1;        // 一個(gè)停止位
    USART_InitStructure.USART_Parity     = USART_Parity_No;         // 無(wú)奇偶校驗(yàn)位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 使能收、發(fā)模式
    USART_Init(USART1, &USART_InitStructure);                       // 初始化串口

    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                  // 使能接受中斷
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);                  // 使能空閑中斷

    USART_Cmd(USART1, ENABLE);                                      // 使能串口, 開(kāi)始工作

    USART1->SR = ~(0x00F0);                                         // 清理中斷

    xUSART.USART1InitFlag = 1;                                      // 標(biāo)記初始化標(biāo)志
    xUSART.USART1ReceivedNum = 0;                                   // 接收字節(jié)數(shù)清零

    printf("\r\r\r=========== 魔女開(kāi)發(fā)板 STM32F103 外設(shè)初始報(bào)告 ===========\r");
    printf("USART1初始化配置      接收中斷、空閑中斷, 發(fā)送中斷\r");
}

/******************************************************************************
 * 函  數(shù): USART1_IRQHandler
 * 功  能: USART1的接收中斷、空閑中斷、發(fā)送中斷
 * 參  數(shù): 無(wú)
 * 返回值: 無(wú)
 *
******************************************************************************/
static uint8_t U1TxBuffer[256] ;    // 用于中斷發(fā)送:環(huán)形緩沖區(qū),256個(gè)字節(jié)
static uint8_t U1TxCounter = 0 ;    // 用于中斷發(fā)送:標(biāo)記已發(fā)送的字節(jié)數(shù)(環(huán)形)
static uint8_t U1TxCount   = 0 ;    // 用于中斷發(fā)送:標(biāo)記將要發(fā)送的字節(jié)數(shù)(環(huán)形)

void USART1_IRQHandler(void)
{
    static uint16_t cnt = 0;                                         // 接收字節(jié)數(shù)累計(jì):每一幀數(shù)據(jù)已接收到的字節(jié)數(shù)
    static uint8_t  RxTemp[U1_RX_BUF_SIZE];                          // 接收數(shù)據(jù)緩存數(shù)組:每新接收1個(gè)字節(jié),先順序存放到這里,當(dāng)一幀接收完(發(fā)生空閑中斷), 再轉(zhuǎn)存到全局變量:xUSART.USARTxReceivedBuffer[xx]中;

    // 接收中斷
    if (USART1->SR & (1 << 5))                                       // 檢查RXNE(讀數(shù)據(jù)寄存器非空標(biāo)志位); RXNE中斷清理方法:讀DR時(shí)自動(dòng)清理;
    {
        if ((cnt >= U1_RX_BUF_SIZE))//||(xUSART.USART1ReceivedFlag==1// 判斷1: 當(dāng)前幀已接收到的數(shù)據(jù)量,已滿(mǎn)(緩存區(qū)), 為避免溢出,本包后面接收到的數(shù)據(jù)直接舍棄.
        {
            // 判斷2: 如果之前接收好的數(shù)據(jù)包還沒(méi)處理,就放棄新數(shù)據(jù),即,新數(shù)據(jù)幀不能覆蓋舊數(shù)據(jù)幀,直至舊數(shù)據(jù)幀被處理.缺點(diǎn):數(shù)據(jù)傳輸過(guò)快于處理速度時(shí)會(huì)掉包;好處:機(jī)制清晰,易于調(diào)試
            USART1->DR;                                              // 讀取數(shù)據(jù)寄存器的數(shù)據(jù),但不保存.主要作用:讀DR時(shí)自動(dòng)清理接收中斷標(biāo)志;
            return;
        }
        RxTemp[cnt++] = USART1->DR ;                                 // 把新收到的字節(jié)數(shù)據(jù),順序存放到RXTemp數(shù)組中;注意:讀取DR時(shí)自動(dòng)清零中斷位;
    }

    // 空閑中斷, 用于配合接收中斷,以判斷一幀數(shù)據(jù)的接收完成
    if (USART1->SR & (1 << 4))                                       // 檢查IDLE(空閑中斷標(biāo)志位); IDLE中斷標(biāo)志清理方法:序列清零,USART1 ->SR;  USART1 ->DR;
    {
        xUSART.USART1ReceivedNum  = 0;                               // 把接收到的數(shù)據(jù)字節(jié)數(shù)清0
        memcpy(xUSART.USART1ReceivedBuffer, RxTemp, U1_RX_BUF_SIZE); // 把本幀接收到的數(shù)據(jù),存放到全局變量xUSART.USARTxReceivedBuffer中, 等待處理; 注意:復(fù)制的是整個(gè)數(shù)組,包括0值,以方便字符串?dāng)?shù)據(jù)
        xUSART.USART1ReceivedNum  = cnt;                             // 把接收到的字節(jié)數(shù),存放到全局變量xUSART.USARTxReceivedCNT中;
        cnt = 0;                                                     // 接收字節(jié)數(shù)累計(jì)器,清零; 準(zhǔn)備下一次的接收
        memset(RxTemp, 0, U1_RX_BUF_SIZE);                           // 接收數(shù)據(jù)緩存數(shù)組,清零; 準(zhǔn)備下一次的接收
        USART1 ->SR;
        USART1 ->DR;                                 // 清零IDLE中斷標(biāo)志位!! 序列清零,順序不能錯(cuò)!!
    }

    // 發(fā)送中斷
    if ((USART1->SR & 1 << 7) && (USART1->CR1 & 1 << 7))             // 檢查T(mén)XE(發(fā)送數(shù)據(jù)寄存器空)、TXEIE(發(fā)送緩沖區(qū)空中斷使能)
    {
        USART1->DR = U1TxBuffer[U1TxCounter++];                      // 讀取數(shù)據(jù)寄存器值;注意:讀取DR時(shí)自動(dòng)清零中斷位;
        if (U1TxCounter == U1TxCount)
            USART1->CR1 &= ~(1 << 7);                                // 已發(fā)送完成,關(guān)閉發(fā)送緩沖區(qū)空置中斷 TXEIE
    }
}

/******************************************************************************
 * 函  數(shù): vUSART1_GetBuffer
 * 功  能: 獲取UART所接收到的數(shù)據(jù)
 * 參  數(shù): uint8_t* buffer   數(shù)據(jù)存放緩存地址
 *          uint8_t* cnt      接收到的字節(jié)數(shù)
 * 返回值: 0_沒(méi)有接收到新數(shù)據(jù), 非0_所接收到新數(shù)據(jù)的字節(jié)數(shù)
 ******************************************************************************/
uint8_t USART1_GetBuffer(uint8_t *buffer, uint8_t *cnt)
{
    if (xUSART.USART1ReceivedNum > 0)                                           // 判斷是否有新數(shù)據(jù)
    {
        memcpy(buffer, xUSART.USART1ReceivedBuffer, xUSART.USART1ReceivedNum);  // 把新數(shù)據(jù)復(fù)制到指定位置
        *cnt = xUSART.USART1ReceivedNum;                                        // 把新數(shù)據(jù)的字節(jié)數(shù),存放指定變量
        xUSART.USART1ReceivedNum = 0;                                           // 接收標(biāo)記置0
        return *cnt;                                                            // 返回所接收到新數(shù)據(jù)的字節(jié)數(shù)
    }
    return 0;                                                                   // 返回0, 表示沒(méi)有接收到新數(shù)據(jù)
}

/******************************************************************************
 * 函  數(shù): vUSART1_SendData
 * 功  能: UART通過(guò)中斷發(fā)送數(shù)據(jù),適合各種數(shù)據(jù)類(lèi)型
 *         【適合場(chǎng)景】本函數(shù)可發(fā)送各種數(shù)據(jù),而不限于字符串,如int,char
 *         【不 適 合】注意環(huán)形緩沖區(qū)容量256字節(jié),如果發(fā)送頻率太高,注意波特率
 * 參  數(shù): uint8_t* buffer   需發(fā)送數(shù)據(jù)的首地址
 *          uint8_t  cnt      發(fā)送的字節(jié)數(shù) ,限于中斷發(fā)送的緩存區(qū)大小,不能大于256個(gè)字節(jié)
 * 返回值:
 ******************************************************************************/
void USART1_SendData(uint8_t *buf, uint8_t cnt)
{
    for (uint8_t i = 0; i < cnt; i++)
        U1TxBuffer[U1TxCount++] = buf[i];

    if ((USART1->CR1 & 1 << 7) == 0)       // 檢查發(fā)送緩沖區(qū)空置中斷(TXEIE)是否已打開(kāi)
        USART1->CR1 |= 1 << 7;
}

/******************************************************************************
 * 函  數(shù): vUSART1_SendString
 * 功  能: UART通過(guò)中斷發(fā)送輸出字符串,無(wú)需輸入數(shù)據(jù)長(zhǎng)度
 *         【適合場(chǎng)景】字符串,長(zhǎng)度<=256字節(jié)
 *         【不 適 合】int,float等數(shù)據(jù)類(lèi)型
 * 參  數(shù): char* stringTemp   需發(fā)送數(shù)據(jù)的緩存首地址
 * 返回值: 元
 ******************************************************************************/
void USART1_SendString(char *stringTemp)
{
    u16 num = 0;                                 // 字符串長(zhǎng)度
    char *t = stringTemp ;                       // 用于配合計(jì)算發(fā)送的數(shù)量
    while (*t++ != 0)  num++;                    // 計(jì)算要發(fā)送的數(shù)目,這步比較耗時(shí),測(cè)試發(fā)現(xiàn)每多6個(gè)字節(jié),增加1us,單位:8位
    USART1_SendData((u8 *)stringTemp, num);      // 注意調(diào)用函數(shù)所需要的真實(shí)數(shù)據(jù)長(zhǎng)度; 如果目標(biāo)需要以0作結(jié)尾判斷,需num+1:字符串以0結(jié)尾,即多發(fā)一個(gè):0
}

/******************************************************************************
 * 函  數(shù): vUSART1_SendStringForDMA
 * 功  能: UART通過(guò)DMA發(fā)送數(shù)據(jù),省了占用中斷的時(shí)間
 *         【適合場(chǎng)景】字符串,字節(jié)數(shù)非常多,
 *         【不 適 合】1:只適合發(fā)送字符串,不適合發(fā)送可能含0的數(shù)值類(lèi)數(shù)據(jù); 2-時(shí)間間隔要足夠
 * 參  數(shù): char strintTemp  要發(fā)送的字符串首地址
 * 返回值: 無(wú)
 ******************************************************************************/
void USART1_SendStringForDMA(char *stringTemp)
{
    static u8 Flag_DmaTxInit = 0;                // 用于標(biāo)記是否已配置DMA發(fā)送
    u32   num = 0;                               // 發(fā)送的數(shù)量,注意發(fā)送的單位不是必須8位的
    char *t = stringTemp ;                       // 用于配合計(jì)算發(fā)送的數(shù)量

    while (*t++ != 0)  num++;                    // 計(jì)算要發(fā)送的數(shù)目,這步比較耗時(shí),測(cè)試發(fā)現(xiàn)每多6個(gè)字節(jié),增加1us,單位:8位

    while (DMA1_Channel4->CNDTR > 0);            // 重要:如果DMA還在進(jìn)行上次發(fā)送,就等待; 得進(jìn)完成中斷清標(biāo)志,F(xiàn)4不用這么麻煩,發(fā)送完后EN自動(dòng)清零
    if (Flag_DmaTxInit == 0)                     // 是否已進(jìn)行過(guò)USAART_TX的DMA傳輸配置
    {
        Flag_DmaTxInit  = 1;                     // 設(shè)置標(biāo)記,下次調(diào)用本函數(shù)就不再進(jìn)行配置了
        USART1 ->CR3   |= 1 << 7;                // 使能DMA發(fā)送
        RCC->AHBENR    |= 1 << 0;                // 開(kāi)啟DMA1時(shí)鐘  [0]DMA1   [1]DMA2

        DMA1_Channel4->CCR   = 0;                // 失能, 清0整個(gè)寄存器, DMA必須失能才能配置
        DMA1_Channel4->CNDTR = num;              // 傳輸數(shù)據(jù)量
        DMA1_Channel4->CMAR  = (u32)stringTemp;  // 存儲(chǔ)器地址
        DMA1_Channel4->CPAR  = (u32)&USART1->DR; // 外設(shè)地址

        DMA1_Channel4->CCR |= 1 << 4;            // 數(shù)據(jù)傳輸方向   0:從外設(shè)讀   1:從存儲(chǔ)器讀
        DMA1_Channel4->CCR |= 0 << 5;            // 循環(huán)模式       0:不循環(huán)     1:循環(huán)
        DMA1_Channel4->CCR |= 0 << 6;            // 外設(shè)地址非增量模式
        DMA1_Channel4->CCR |= 1 << 7;            // 存儲(chǔ)器增量模式
        DMA1_Channel4->CCR |= 0 << 8;            // 外設(shè)數(shù)據(jù)寬度為8位
        DMA1_Channel4->CCR |= 0 << 10;           // 存儲(chǔ)器數(shù)據(jù)寬度8位
        DMA1_Channel4->CCR |= 0 << 12;           // 中等優(yōu)先級(jí)
        DMA1_Channel4->CCR |= 0 << 14;           // 非存儲(chǔ)器到存儲(chǔ)器模式
    }
    DMA1_Channel4->CCR  &= ~((u32)(1 << 0));     // 失能,DMA必須失能才能配置
    DMA1_Channel4->CNDTR = num;                  // 傳輸數(shù)據(jù)量
    DMA1_Channel4->CMAR  = (u32)stringTemp;      // 存儲(chǔ)器地址
    DMA1_Channel4->CCR  |= 1 << 0;               // 開(kāi)啟DMA傳輸
}






//   USART-2   //
/
/******************************************************************************
 * 函  數(shù): vUSART2_Init
 * 功  能: 初始化USART的GPIO、通信參數(shù)配置、中斷優(yōu)先級(jí)
 *          (8位數(shù)據(jù)、無(wú)校驗(yàn)、1個(gè)停止位)
 * 參  數(shù): uint32_t baudrate  通信波特率
 * 返回值: 無(wú)
 ******************************************************************************/
void USART2_Init(uint32_t baudrate)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    NVIC_InitTypeDef  NVIC_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    // 時(shí)鐘使能
    RCC->APB1ENR |= RCC_APB1ENR_USART2EN;                           // 使能USART2時(shí)鐘
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;                             // 使能GPIOA時(shí)鐘

    // GPIO_TX引腳配置
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;                // TX引腳工作模式:復(fù)用推挽
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // GPIO_RX引腳配置
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;                  // RX引腳工作模式:上拉輸入; 如果使用浮空輸入,引腳空置時(shí)可能產(chǎn)生誤輸入; 當(dāng)電路上為一主多從電路時(shí),可以使用復(fù)用開(kāi)漏模式
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    // 中斷配置
    NVIC_InitStructure .NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure .NVIC_IRQChannelPreemptionPriority = 2 ;     // 搶占優(yōu)先級(jí)
    NVIC_InitStructure .NVIC_IRQChannelSubPriority = 2;             // 子優(yōu)先級(jí)
    NVIC_InitStructure .NVIC_IRQChannelCmd = ENABLE;                // IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);

    //USART 初始化設(shè)置
    //USART_DeInit(USART2);
    USART_InitStructure.USART_BaudRate   = baudrate;                // 串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;     // 字長(zhǎng)為8位數(shù)據(jù)格式
    USART_InitStructure.USART_StopBits   = USART_StopBits_1;        // 一個(gè)停止位
    USART_InitStructure.USART_Parity     = USART_Parity_No;         // 無(wú)奇偶校驗(yàn)位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 使能收、發(fā)模式
    USART_Init(USART2, &USART_InitStructure);                       // 初始化串口

    USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);                  // 使能接受中斷
    USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);                  // 使能空閑中斷

    USART_Cmd(USART2, ENABLE);                                      // 使能串口, 開(kāi)始工作

    USART2->SR = ~(0x00F0);                                         // 清理中斷

    xUSART.USART2InitFlag = 1;                                      // 標(biāo)記初始化標(biāo)志
    xUSART.USART2ReceivedNum = 0;                                   // 接收字節(jié)數(shù)清零

    printf("\rUSART2初始化配置      接收中斷、空閑中斷, 發(fā)送中斷\r");
}

/******************************************************************************
 * 函  數(shù): USART2_IRQHandler
 * 功  能: USART2的接收中斷、空閑中斷、發(fā)送中斷
 * 參  數(shù): 無(wú)
 * 返回值: 無(wú)
 ******************************************************************************/
static uint8_t U2TxBuffer[256] ;    // 用于中斷發(fā)送:環(huán)形緩沖區(qū),256個(gè)字節(jié)
static uint8_t U2TxCounter = 0 ;    // 用于中斷發(fā)送:標(biāo)記已發(fā)送的字節(jié)數(shù)(環(huán)形)
static uint8_t U2TxCount   = 0 ;    // 用于中斷發(fā)送:標(biāo)記將要發(fā)送的字節(jié)數(shù)(環(huán)形)

void USART2_IRQHandler(void)
{
    static uint16_t cnt = 0;                                         // 接收字節(jié)數(shù)累計(jì):每一幀數(shù)據(jù)已接收到的字節(jié)數(shù)
    static uint8_t  RxTemp[U2_RX_BUF_SIZE];                          // 接收數(shù)據(jù)緩存數(shù)組:每新接收1個(gè)字節(jié),先順序存放到這里,當(dāng)一幀接收完(發(fā)生空閑中斷), 再轉(zhuǎn)存到全局變量:xUSART.USARTxReceivedBuffer[xx]中;

    // 接收中斷
    if (USART2->SR & (1 << 5))                                       // 檢查RXNE(讀數(shù)據(jù)寄存器非空標(biāo)志位); RXNE中斷清理方法:讀DR時(shí)自動(dòng)清理;
    {
        if ((cnt >= U2_RX_BUF_SIZE))//||xUSART.USART2ReceivedFlag==1 // 判斷1: 當(dāng)前幀已接收到的數(shù)據(jù)量,已滿(mǎn)(緩存區(qū)), 為避免溢出,本包后面接收到的數(shù)據(jù)直接舍棄.
        {
            // 判斷2: 如果之前接收好的數(shù)據(jù)包還沒(méi)處理,就放棄新數(shù)據(jù),即,新數(shù)據(jù)幀不能覆蓋舊數(shù)據(jù)幀,直至舊數(shù)據(jù)幀被處理.缺點(diǎn):數(shù)據(jù)傳輸過(guò)快于處理速度時(shí)會(huì)掉包;好處:機(jī)制清晰,易于調(diào)試
            USART2->DR;                                              // 讀取數(shù)據(jù)寄存器的數(shù)據(jù),但不保存.主要作用:讀DR時(shí)自動(dòng)清理接收中斷標(biāo)志;
            return;
        }
        RxTemp[cnt++] = USART2->DR ;                                 // 把新收到的字節(jié)數(shù)據(jù),順序存放到RXTemp數(shù)組中;注意:讀取DR時(shí)自動(dòng)清零中斷位;
    }

    // 空閑中斷, 用于配合接收中斷,以判斷一幀數(shù)據(jù)的接收完成
    if (USART2->SR & (1 << 4))                                       // 檢查IDLE(空閑中斷標(biāo)志位); IDLE中斷標(biāo)志清理方法:序列清零,USART1 ->SR;  USART1 ->DR;
    {
        xUSART.USART2ReceivedNum  = 0;                               // 把接收到的數(shù)據(jù)字節(jié)數(shù)清0
        memcpy(xUSART.USART2ReceivedBuffer, RxTemp, U2_RX_BUF_SIZE); // 把本幀接收到的數(shù)據(jù),存放到全局變量xUSART.USARTxReceivedBuffer中, 等待處理; 注意:復(fù)制的是整個(gè)數(shù)組,包括0值,以方便字符串?dāng)?shù)據(jù)
        xUSART.USART2ReceivedNum  = cnt;                             // 把接收到的字節(jié)數(shù),存放到全局變量xUSART.USARTxReceivedCNT中;
        cnt = 0;                                                     // 接收字節(jié)數(shù)累計(jì)器,清零; 準(zhǔn)備下一次的接收
        memset(RxTemp, 0, U2_RX_BUF_SIZE);                           // 接收數(shù)據(jù)緩存數(shù)組,清零; 準(zhǔn)備下一次的接收
        USART2 ->SR;
        USART2 ->DR;                                 // 清零IDLE中斷標(biāo)志位!! 序列清零,順序不能錯(cuò)!!
    }

    // 發(fā)送中斷
    if ((USART2->SR & 1 << 7) && (USART2->CR1 & 1 << 7))             // 檢查T(mén)XE(發(fā)送數(shù)據(jù)寄存器空)、TXEIE(發(fā)送緩沖區(qū)空中斷使能)
    {
        USART2->DR = U2TxBuffer[U2TxCounter++];                      // 讀取數(shù)據(jù)寄存器值;注意:讀取DR時(shí)自動(dòng)清零中斷位;
        if (U2TxCounter == U2TxCount)
            USART2->CR1 &= ~(1 << 7);                                // 已發(fā)送完成,關(guān)閉發(fā)送緩沖區(qū)空置中斷 TXEIE
    }
}

/******************************************************************************
 * 函  數(shù): vUSART2_GetBuffer
 * 功  能: 獲取UART所接收到的數(shù)據(jù)
 * 參  數(shù): uint8_t* buffer   數(shù)據(jù)存放緩存地址
 *          uint8_t* cnt      接收到的字節(jié)數(shù)
 * 返回值: 0_沒(méi)有接收到新數(shù)據(jù), 非0_所接收到新數(shù)據(jù)的字節(jié)數(shù)
 ******************************************************************************/
uint8_t USART2_GetBuffer(uint8_t *buffer, uint8_t *cnt)
{
    if (xUSART.USART2ReceivedNum > 0)                                          // 判斷是否有新數(shù)據(jù)
    {
        memcpy(buffer, xUSART.USART2ReceivedBuffer, xUSART.USART2ReceivedNum); // 把新數(shù)據(jù)復(fù)制到指定位置
        *cnt = xUSART.USART2ReceivedNum;                                       // 把新數(shù)據(jù)的字節(jié)數(shù),存放指定變量
        xUSART.USART2ReceivedNum = 0;                                          // 接收標(biāo)記置0
        return *cnt;                                                           // 返回所接收到新數(shù)據(jù)的字節(jié)數(shù)
    }
    return 0;                                                                  // 返回0, 表示沒(méi)有接收到新數(shù)據(jù)
}

/******************************************************************************
 * 函  數(shù): vUSART2_SendData
 * 功  能: UART通過(guò)中斷發(fā)送數(shù)據(jù),適合各種數(shù)據(jù)類(lèi)型
 *         【適合場(chǎng)景】本函數(shù)可發(fā)送各種數(shù)據(jù),而不限于字符串,如int,char
 *         【不 適 合】注意環(huán)形緩沖區(qū)容量256字節(jié),如果發(fā)送頻率太高,注意波特率
 * 參  數(shù): uint8_t* buffer   需發(fā)送數(shù)據(jù)的首地址
 *          uint8_t  cnt      發(fā)送的字節(jié)數(shù) ,限于中斷發(fā)送的緩存區(qū)大小,不能大于256個(gè)字節(jié)
 * 返回值:
 ******************************************************************************/
void USART2_SendData(uint8_t *buf, uint8_t cnt)
{
    for (uint8_t i = 0; i < cnt; i++)
        U2TxBuffer[U2TxCount++] = buf[i];

    if ((USART2->CR1 & 1 << 7) == 0)       // 檢查發(fā)送緩沖區(qū)空置中斷(TXEIE)是否已打開(kāi)
        USART2->CR1 |= 1 << 7;
}

/******************************************************************************
 * 函  數(shù): vUSART2_SendString
 * 功  能: UART通過(guò)中斷發(fā)送輸出字符串,無(wú)需輸入數(shù)據(jù)長(zhǎng)度
 *         【適合場(chǎng)景】字符串,長(zhǎng)度<=256字節(jié)
 *         【不 適 合】int,float等數(shù)據(jù)類(lèi)型
 * 參  數(shù): char* stringTemp   需發(fā)送數(shù)據(jù)的緩存首地址
 * 返回值: 元
 ******************************************************************************/
void USART2_SendString(char *stringTemp)
{
    u16 num = 0;                                 // 字符串長(zhǎng)度
    char *t = stringTemp ;                       // 用于配合計(jì)算發(fā)送的數(shù)量
    while (*t++ != 0)  num++;                    // 計(jì)算要發(fā)送的數(shù)目,這步比較耗時(shí),測(cè)試發(fā)現(xiàn)每多6個(gè)字節(jié),增加1us,單位:8位
    USART2_SendData((u8 *)stringTemp, num);      // 注意調(diào)用函數(shù)所需要的真實(shí)數(shù)據(jù)長(zhǎng)度; 如果目標(biāo)需要以0作結(jié)尾判斷,需num+1:字符串以0結(jié)尾,即多發(fā)一個(gè):0
}

/******************************************************************************
 * 函  數(shù): USART3_IRQHandler
 * 功  能: USART的接收中斷、空閑中斷、發(fā)送中斷
 * 參  數(shù): 無(wú)
 * 返回值: 無(wú)
 ******************************************************************************/
static uint8_t U3TxBuffer[256] ;    // 用于中斷發(fā)送:環(huán)形緩沖區(qū),256個(gè)字節(jié)
static uint8_t U3TxCounter = 0 ;    // 用于中斷發(fā)送:標(biāo)記已發(fā)送的字節(jié)數(shù)(環(huán)形)
static uint8_t U3TxCount   = 0 ;    // 用于中斷發(fā)送:標(biāo)記將要發(fā)送的字節(jié)數(shù)(環(huán)形)

void USART3_SendData(uint8_t *buf, uint8_t cnt)
{
    for (uint8_t i = 0; i < cnt; i++)
        U3TxBuffer[U3TxCount++] = buf[i];

    if ((USART3->CR1 & 1 << 7) == 0)       // 檢查發(fā)送緩沖區(qū)空置中斷(TXEIE)是否已打開(kāi)
        USART3->CR1 |= 1 << 7;
}

/******************************************************************************
 * 函  數(shù): vUSART3_SendString
 * 功  能: UART通過(guò)中斷發(fā)送輸出字符串,無(wú)需輸入數(shù)據(jù)長(zhǎng)度
 *         【適合場(chǎng)景】字符串,長(zhǎng)度<=256字節(jié)
 *         【不 適 合】int,float等數(shù)據(jù)類(lèi)型
 * 參  數(shù): char* stringTemp   需發(fā)送數(shù)據(jù)的緩存首地址
 * 返回值: 元
 ******************************************************************************/
//void USART3_SendString(char *stringTemp)
//{
//    u16 num = 0;                                 // 字符串長(zhǎng)度
//    char *t = stringTemp ;                       // 用于配合計(jì)算發(fā)送的數(shù)量
//    while (*t++ != 0)  num++;                    // 計(jì)算要發(fā)送的數(shù)目,這步比較耗時(shí),測(cè)試發(fā)現(xiàn)每多6個(gè)字節(jié),增加1us,單位:8位
//    USART3_SendData((u8 *)stringTemp, num);      // 注意調(diào)用函數(shù)所需要的真實(shí)數(shù)據(jù)長(zhǎng)度; 如果目標(biāo)需要以0作結(jié)尾判斷,需num+1:字符串以0結(jié)尾,即多發(fā)一個(gè):0
//}


#ifdef STM32F10X_HD  // STM32F103R,及以上,才有UART4和UART5

//   UART-4   //
/
/******************************************************************************
 * 函  數(shù): vUART4_Init
 * 功  能: 初始化USART的GPIO、通信參數(shù)配置、中斷優(yōu)先級(jí)
 *          (8位數(shù)據(jù)、無(wú)校驗(yàn)、1個(gè)停止位)
 * 參  數(shù): uint32_t baudrate  通信波特率
 * 返回值: 無(wú)
 ******************************************************************************/
void UART4_Init(uint32_t baudrate)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    NVIC_InitTypeDef  NVIC_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    // 時(shí)鐘使能
    RCC->APB1ENR |= RCC_APB1ENR_UART4EN;                            // 使能UART4時(shí)鐘
    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;                             // 使能GPIOC時(shí)鐘

    // GPIO_TX引腳配置
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;                // TX引腳工作模式:復(fù)用推挽    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    // GPIO_RX引腳配置
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;                  // RX引腳工作模式:上拉輸入; 如果使用浮空輸入,引腳空置時(shí)可能產(chǎn)生誤輸入; 當(dāng)電路上為一主多從電路時(shí),可以使用復(fù)用開(kāi)漏模式
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    // 中斷配置
    NVIC_InitStructure .NVIC_IRQChannel = UART4_IRQn;
    NVIC_InitStructure .NVIC_IRQChannelPreemptionPriority = 2 ;     // 搶占優(yōu)先級(jí)
    NVIC_InitStructure .NVIC_IRQChannelSubPriority = 2;             // 子優(yōu)先級(jí)
    NVIC_InitStructure .NVIC_IRQChannelCmd = ENABLE;                // IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);

    //USART 初始化設(shè)置
    USART_DeInit(UART4);
    USART_InitStructure.USART_BaudRate   = baudrate;                // 串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;     // 字長(zhǎng)為8位數(shù)據(jù)格式
    USART_InitStructure.USART_StopBits   = USART_StopBits_1;        // 一個(gè)停止位
    USART_InitStructure.USART_Parity     = USART_Parity_No;         // 無(wú)奇偶校驗(yàn)位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 使能收、發(fā)模式
    USART_Init(UART4, &USART_InitStructure);                        // 初始化串口

    USART_ITConfig(UART4, USART_IT_TXE, DISABLE);
    USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);                   // 使能接受中斷
    USART_ITConfig(UART4, USART_IT_IDLE, ENABLE);                   // 使能空閑中斷
    
    USART_Cmd(UART4, ENABLE);                                       // 使能串口, 開(kāi)始工作

    UART4->SR = ~(0x00F0);                                          // 清理中斷

    xUSART.UART4InitFlag = 1;                                       // 標(biāo)記初始化標(biāo)志
    xUSART.UART4ReceivedNum = 0;                                    // 接收字節(jié)數(shù)清零

    printf("\rUART4 初始化配置      接收中斷、空閑中斷, 發(fā)送中斷\r");
}

/******************************************************************************
 * 函  數(shù): UART4_IRQHandler
 * 功  能: USART2的接收中斷、空閑中斷、發(fā)送中斷
 * 參  數(shù): 無(wú)
 * 返回值: 無(wú)
 ******************************************************************************/
static uint8_t U4TxBuffer[256] ;    // 用于中斷發(fā)送:環(huán)形緩沖區(qū),256個(gè)字節(jié)
static uint8_t U4TxCounter = 0 ;    // 用于中斷發(fā)送:標(biāo)記已發(fā)送的字節(jié)數(shù)(環(huán)形)
static uint8_t U4TxCount   = 0 ;    // 用于中斷發(fā)送:標(biāo)記將要發(fā)送的字節(jié)數(shù)(環(huán)形)

void UART4_IRQHandler(void)
{
    static uint16_t cnt = 0;                                        // 接收字節(jié)數(shù)累計(jì):每一幀數(shù)據(jù)已接收到的字節(jié)數(shù)
    static uint8_t  RxTemp[U4_RX_BUF_SIZE];                         // 接收數(shù)據(jù)緩存數(shù)組:每新接收1個(gè)字節(jié),先順序存放到這里,當(dāng)一幀接收完(發(fā)生空閑中斷), 再轉(zhuǎn)存到全局變量:xUSART.USARTxReceivedBuffer[xx]中;

    // 接收中斷
    if (UART4->SR & (1 << 5))                                       // 檢查RXNE(讀數(shù)據(jù)寄存器非空標(biāo)志位); RXNE中斷清理方法:讀DR時(shí)自動(dòng)清理;
    {
        if ((cnt >= U4_RX_BUF_SIZE))//||xUSART.UART4ReceivedFlag==1 // 判斷1: 當(dāng)前幀已接收到的數(shù)據(jù)量,已滿(mǎn)(緩存區(qū)), 為避免溢出,本包后面接收到的數(shù)據(jù)直接舍棄.
        {
            // 判斷2: 如果之前接收好的數(shù)據(jù)包還沒(méi)處理,就放棄新數(shù)據(jù),即,新數(shù)據(jù)幀不能覆蓋舊數(shù)據(jù)幀,直至舊數(shù)據(jù)幀被處理.缺點(diǎn):數(shù)據(jù)傳輸過(guò)快于處理速度時(shí)會(huì)掉包;好處:機(jī)制清晰,易于調(diào)試
            UART4->DR;                                              // 讀取數(shù)據(jù)寄存器的數(shù)據(jù),但不保存.主要作用:讀DR時(shí)自動(dòng)清理接收中斷標(biāo)志;
            return;
        }
        RxTemp[cnt++] = UART4->DR ;                                 // 把新收到的字節(jié)數(shù)據(jù),順序存放到RXTemp數(shù)組中;注意:讀取DR時(shí)自動(dòng)清零中斷位;
    }

    // 空閑中斷, 用于配合接收中斷,以判斷一幀數(shù)據(jù)的接收完成
    if (UART4->SR & (1 << 4))                                       // 檢查IDLE(空閑中斷標(biāo)志位); IDLE中斷標(biāo)志清理方法:序列清零,USART1 ->SR;  USART1 ->DR;
    {
        xUSART.UART4ReceivedNum  = 0;                               // 把接收到的數(shù)據(jù)字節(jié)數(shù)清0
        memcpy(xUSART.UART4ReceivedBuffer, RxTemp, U4_RX_BUF_SIZE); // 把本幀接收到的數(shù)據(jù),存放到全局變量xUSART.USARTxReceivedBuffer中, 等待處理; 注意:復(fù)制的是整個(gè)數(shù)組,包括0值,以方便字符串?dāng)?shù)據(jù)
        xUSART.UART4ReceivedNum  = cnt;                             // 把接收到的字節(jié)數(shù),存放到全局變量xUSART.USARTxReceivedCNT中;
        cnt = 0;                                                    // 接收字節(jié)數(shù)累計(jì)器,清零; 準(zhǔn)備下一次的接收
        memset(RxTemp, 0, U4_RX_BUF_SIZE);                          // 接收數(shù)據(jù)緩存數(shù)組,清零; 準(zhǔn)備下一次的接收
        UART4 ->SR;
        UART4 ->DR;                                  // 清零IDLE中斷標(biāo)志位!! 序列清零,順序不能錯(cuò)!!
    }

    // 發(fā)送中斷
    if ((UART4->SR & 1 << 7) && (UART4->CR1 & 1 << 7))              // 檢查T(mén)XE(發(fā)送數(shù)據(jù)寄存器空)、TXEIE(發(fā)送緩沖區(qū)空中斷使能)
    {
        UART4->DR = U4TxBuffer[U4TxCounter++];                      // 讀取數(shù)據(jù)寄存器值;注意:讀取DR時(shí)自動(dòng)清零中斷位;
        if (U4TxCounter == U4TxCount)
            UART4->CR1 &= ~(1 << 7);                                // 已發(fā)送完成,關(guān)閉發(fā)送緩沖區(qū)空置中斷 TXEIE
    }
}

/******************************************************************************
 * 函  數(shù): vUART4_GetBuffer
 * 功  能: 獲取UART所接收到的數(shù)據(jù)
 * 參  數(shù): uint8_t* buffer   數(shù)據(jù)存放緩存地址
 *          uint8_t* cnt      接收到的字節(jié)數(shù)
 * 返回值: 0_沒(méi)有接收到新數(shù)據(jù), 非0_所接收到新數(shù)據(jù)的字節(jié)數(shù)
 ******************************************************************************/
uint8_t UART4_GetBuffer(uint8_t *buffer, uint8_t *cnt)
{
    if (xUSART.UART4ReceivedNum > 0)                                         // 判斷是否有新數(shù)據(jù)
    {
        memcpy(buffer, xUSART.UART4ReceivedBuffer, xUSART.UART4ReceivedNum); // 把新數(shù)據(jù)復(fù)制到指定位置
        *cnt = xUSART.UART4ReceivedNum;                                      // 把新數(shù)據(jù)的字節(jié)數(shù),存放指定變量
        xUSART.UART4ReceivedNum = 0;                                         // 接收標(biāo)記置0
        return *cnt;                                                         // 返回所接收到新數(shù)據(jù)的字節(jié)數(shù)
    }
    return 0;                                                                // 返回0, 表示沒(méi)有接收到新數(shù)據(jù)
}

/******************************************************************************
 * 函  數(shù): vUART4_SendData
 * 功  能: UART通過(guò)中斷發(fā)送數(shù)據(jù),適合各種數(shù)據(jù)類(lèi)型
 *         【適合場(chǎng)景】本函數(shù)可發(fā)送各種數(shù)據(jù),而不限于字符串,如int,char
 *         【不 適 合】注意環(huán)形緩沖區(qū)容量256字節(jié),如果發(fā)送頻率太高,注意波特率
 * 參  數(shù): uint8_t* buffer   需發(fā)送數(shù)據(jù)的首地址
 *          uint8_t  cnt      發(fā)送的字節(jié)數(shù) ,限于中斷發(fā)送的緩存區(qū)大小,不能大于256個(gè)字節(jié)
 * 返回值:
 ******************************************************************************/
void UART4_SendData(uint8_t *buf, uint8_t cnt)
{
    for (uint8_t i = 0; i < cnt; i++)
        U4TxBuffer[U4TxCount++] = buf[i];

    if ((UART4->CR1 & 1 << 7) == 0)       // 檢查發(fā)送緩沖區(qū)空置中斷(TXEIE)是否已打開(kāi)
        UART4->CR1 |= 1 << 7;
}

/******************************************************************************
 * 函  數(shù): vUART4_SendString
 * 功  能: UART通過(guò)中斷發(fā)送輸出字符串,無(wú)需輸入數(shù)據(jù)長(zhǎng)度
 *         【適合場(chǎng)景】字符串,長(zhǎng)度<=256字節(jié)
 *         【不 適 合】int,float等數(shù)據(jù)類(lèi)型
 * 參  數(shù): char* stringTemp   需發(fā)送數(shù)據(jù)的緩存首地址
 * 返回值: 元
 ******************************************************************************/
void UART4_SendString(char *stringTemp)
{
    u16 num = 0;                                 // 字符串長(zhǎng)度
    char *t = stringTemp ;                       // 用于配合計(jì)算發(fā)送的數(shù)量
    while (*t++ != 0)  num++;                    // 計(jì)算要發(fā)送的數(shù)目,這步比較耗時(shí),測(cè)試發(fā)現(xiàn)每多6個(gè)字節(jié),增加1us,單位:8位
    UART4_SendData((u8 *)stringTemp, num);       // 調(diào)用函數(shù)完成發(fā)送,num+1:字符串以0結(jié)尾,需多發(fā)一個(gè):0
}




//   UART-4   //
/
/******************************************************************************
 * 函  數(shù): vUART5_Init
 * 功  能: 初始化USART的GPIO、通信參數(shù)配置、中斷優(yōu)先級(jí)
 *          (8位數(shù)據(jù)、無(wú)校驗(yàn)、1個(gè)停止位)
 * 參  數(shù): uint32_t baudrate  通信波特率
 * 返回值: 無(wú)
 ******************************************************************************/
void UART5_Init(uint32_t baudrate)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    NVIC_InitTypeDef  NVIC_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    // 時(shí)鐘使能
    RCC->APB1ENR |= RCC_APB1ENR_UART5EN;                            // 使能UART5時(shí)鐘
    RCC->APB2ENR |= RCC_APB2ENR_IOPDEN | RCC_APB2ENR_IOPCEN;        // 使能GPIO時(shí)鐘

    // GPIO_TX引腳配置
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;                // TX引腳工作模式:復(fù)用推挽
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    // GPIO_RX引腳配置
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;                  // RX引腳工作模式:上拉輸入; 如果使用浮空輸入,引腳空置時(shí)可能產(chǎn)生誤輸入; 當(dāng)電路上為一主多從電路時(shí),可以使用復(fù)用開(kāi)漏模式
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    // 中斷配置
    NVIC_InitStructure .NVIC_IRQChannel = UART5_IRQn;
    NVIC_InitStructure .NVIC_IRQChannelPreemptionPriority = 2 ;     // 搶占優(yōu)先級(jí)
    NVIC_InitStructure .NVIC_IRQChannelSubPriority = 2;             // 子優(yōu)先級(jí)
    NVIC_InitStructure .NVIC_IRQChannelCmd = ENABLE;                // IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);

    //USART 初始化設(shè)置
    USART_DeInit(UART5);
    USART_InitStructure.USART_BaudRate   = baudrate;                // 串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;     // 字長(zhǎng)為8位數(shù)據(jù)格式
    USART_InitStructure.USART_StopBits   = USART_StopBits_1;        // 一個(gè)停止位
    USART_InitStructure.USART_Parity     = USART_Parity_No;         // 無(wú)奇偶校驗(yàn)位
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 使能收、發(fā)模式
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init(UART5, &USART_InitStructure);                        // 初始化串口

    USART_ITConfig(UART5, USART_IT_TXE, DISABLE);
    USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);                   // 使能接受中斷
    USART_ITConfig(UART5, USART_IT_IDLE, ENABLE);                   // 使能空閑中斷

    USART_Cmd(UART5, ENABLE);                                       // 使能串口, 開(kāi)始工作

    UART5->SR = ~(0x00F0);                                          // 清理中斷

    xUSART.UART5InitFlag = 1;                                       // 標(biāo)記初始化標(biāo)志
    xUSART.UART5ReceivedNum = 0;                                    // 接收字節(jié)數(shù)清零

    printf("\rUART5 初始化配置      接收中斷、空閑中斷, 發(fā)送中斷\r");
}

/******************************************************************************
 * 函  數(shù): UART5_IRQHandler
 * 功  能: USART2的接收中斷、空閑中斷、發(fā)送中斷
 * 參  數(shù): 無(wú)
 * 返回值: 無(wú)
 ******************************************************************************/
static uint8_t U5TxBuffer[256] ;    // 用于中斷發(fā)送:環(huán)形緩沖區(qū),256個(gè)字節(jié)
static uint8_t U5TxCounter = 0 ;    // 用于中斷發(fā)送:標(biāo)記已發(fā)送的字節(jié)數(shù)(環(huán)形)
static uint8_t U5TxCount   = 0 ;    // 用于中斷發(fā)送:標(biāo)記將要發(fā)送的字節(jié)數(shù)(環(huán)形)

void UART5_IRQHandler(void)
{
    static uint16_t cnt = 0;                                        // 接收字節(jié)數(shù)累計(jì):每一幀數(shù)據(jù)已接收到的字節(jié)數(shù)
    static uint8_t  RxTemp[U5_RX_BUF_SIZE];                         // 接收數(shù)據(jù)緩存數(shù)組:每新接收1個(gè)字節(jié),先順序存放到這里,當(dāng)一幀接收完(發(fā)生空閑中斷), 再轉(zhuǎn)存到全局變量:xUSART.USARTxReceivedBuffer[xx]中;

    // 接收中斷
    if (UART5->SR & (1 << 5))                                       // 檢查RXNE(讀數(shù)據(jù)寄存器非空標(biāo)志位); RXNE中斷清理方法:讀DR時(shí)自動(dòng)清理;
    {
        if ((cnt >= U5_RX_BUF_SIZE))//||xUSART.UART5ReceivedFlag==1 // 判斷1: 當(dāng)前幀已接收到的數(shù)據(jù)量,已滿(mǎn)(緩存區(qū)), 為避免溢出,本包后面接收到的數(shù)據(jù)直接舍棄.
        {
            // 判斷2: 如果之前接收好的數(shù)據(jù)包還沒(méi)處理,就放棄新數(shù)據(jù),即,新數(shù)據(jù)幀不能覆蓋舊數(shù)據(jù)幀,直至舊數(shù)據(jù)幀被處理.缺點(diǎn):數(shù)據(jù)傳輸過(guò)快于處理速度時(shí)會(huì)掉包;好處:機(jī)制清晰,易于調(diào)試
            UART5->DR;                                              // 讀取數(shù)據(jù)寄存器的數(shù)據(jù),但不保存.主要作用:讀DR時(shí)自動(dòng)清理接收中斷標(biāo)志;
            return;
        }
        RxTemp[cnt++] = UART5->DR ;                                 // 把新收到的字節(jié)數(shù)據(jù),順序存放到RXTemp數(shù)組中;注意:讀取DR時(shí)自動(dòng)清零中斷位;
    }

    // 空閑中斷, 用于配合接收中斷,以判斷一幀數(shù)據(jù)的接收完成
    if (UART5->SR & (1 << 4))                                       // 檢查IDLE(空閑中斷標(biāo)志位); IDLE中斷標(biāo)志清理方法:序列清零,USART1 ->SR;  USART1 ->DR;
    {
        xUSART.UART5ReceivedNum  = 0;                               // 把接收到的數(shù)據(jù)字節(jié)數(shù)清0
        memcpy(xUSART.UART5ReceivedBuffer, RxTemp, U5_RX_BUF_SIZE); // 把本幀接收到的數(shù)據(jù),存放到全局變量xUSART.USARTxReceivedBuffer中, 等待處理; 注意:復(fù)制的是整個(gè)數(shù)組,包括0值,以方便字符串?dāng)?shù)據(jù)
        xUSART.UART5ReceivedNum  = cnt;                             // 把接收到的字節(jié)數(shù),存放到全局變量xUSART.USARTxReceivedCNT中;
        cnt = 0;                                                    // 接收字節(jié)數(shù)累計(jì)器,清零; 準(zhǔn)備下一次的接收
        memset(RxTemp, 0, U5_RX_BUF_SIZE);                          // 接收數(shù)據(jù)緩存數(shù)組,清零; 準(zhǔn)備下一次的接收
        UART5 ->SR;
        UART5 ->DR;                                  // 清零IDLE中斷標(biāo)志位!! 序列清零,順序不能錯(cuò)!!
    }

    // 發(fā)送中斷
    if ((UART5->SR & 1 << 7) && (UART5->CR1 & 1 << 7))              // 檢查T(mén)XE(發(fā)送數(shù)據(jù)寄存器空)、TXEIE(發(fā)送緩沖區(qū)空中斷使能)
    {
        UART5->DR = U5TxBuffer[U5TxCounter++];                      // 讀取數(shù)據(jù)寄存器值;注意:讀取DR時(shí)自動(dòng)清零中斷位;
        if (U5TxCounter == U5TxCount)
            UART5->CR1 &= ~(1 << 7);                                // 已發(fā)送完成,關(guān)閉發(fā)送緩沖區(qū)空置中斷 TXEIE
    }
}

/******************************************************************************
 * 函  數(shù): vUART5_GetBuffer
 * 功  能: 獲取UART所接收到的數(shù)據(jù)
 * 參  數(shù): uint8_t* buffer   數(shù)據(jù)存放緩存地址
 *          uint8_t* cnt      接收到的字節(jié)數(shù)
 * 返回值: 0_沒(méi)有接收到新數(shù)據(jù), 非0_所接收到新數(shù)據(jù)的字節(jié)數(shù)
 ******************************************************************************/
uint8_t UART5_GetBuffer(uint8_t *buffer, uint8_t *cnt)
{
    if (xUSART.UART5ReceivedNum > 0)                                         // 判斷是否有新數(shù)據(jù)
    {
        memcpy(buffer, xUSART.UART5ReceivedBuffer, xUSART.UART5ReceivedNum); // 把新數(shù)據(jù)復(fù)制到指定位置
        *cnt = xUSART.UART5ReceivedNum;                                      // 把新數(shù)據(jù)的字節(jié)數(shù),存放指定變量
        xUSART.UART5ReceivedNum = 0;                                         // 接收標(biāo)記置0
        return *cnt;                                                         // 返回所接收到新數(shù)據(jù)的字節(jié)數(shù)
    }
    return 0;                                                                // 返回0, 表示沒(méi)有接收到新數(shù)據(jù)
}

/******************************************************************************
 * 函  數(shù): vUART5_SendData
 * 功  能: UART通過(guò)中斷發(fā)送數(shù)據(jù),適合各種數(shù)據(jù)類(lèi)型
 *         【適合場(chǎng)景】本函數(shù)可發(fā)送各種數(shù)據(jù),而不限于字符串,如int,char
 *         【不 適 合】注意環(huán)形緩沖區(qū)容量256字節(jié),如果發(fā)送頻率太高,注意波特率
 * 參  數(shù): uint8_t* buffer   需發(fā)送數(shù)據(jù)的首地址
 *          uint8_t  cnt      發(fā)送的字節(jié)數(shù) ,限于中斷發(fā)送的緩存區(qū)大小,不能大于256個(gè)字節(jié)
 * 返回值:
 ******************************************************************************/
void UART5_SendData(uint8_t *buf, uint8_t cnt)
{
    for (uint8_t i = 0; i < cnt; i++)
        U5TxBuffer[U5TxCount++] = buf[i];

    if ((UART5->CR1 & 1 << 7) == 0)       // 檢查發(fā)送緩沖區(qū)空置中斷(TXEIE)是否已打開(kāi)
        UART5->CR1 |= 1 << 7;
}

/******************************************************************************
 * 函  數(shù): vUART5_SendString
 * 功  能: UART通過(guò)中斷發(fā)送輸出字符串,無(wú)需輸入數(shù)據(jù)長(zhǎng)度
 *         【適合場(chǎng)景】字符串,長(zhǎng)度<=256字節(jié)
 *         【不 適 合】int,float等數(shù)據(jù)類(lèi)型
 * 參  數(shù): char* stringTemp   需發(fā)送數(shù)據(jù)的緩存首地址
 * 返回值: 元
 ******************************************************************************/
void UART5_SendString(char *stringTemp)
{
    u16 num = 0;                                 // 字符串長(zhǎng)度
    char *t = stringTemp ;                       // 用于配合計(jì)算發(fā)送的數(shù)量
    while (*t++ != 0)  num++;                    // 計(jì)算要發(fā)送的數(shù)目,這步比較耗時(shí),測(cè)試發(fā)現(xiàn)每多6個(gè)字節(jié),增加1us,單位:8位
    UART5_SendData((u8 *)stringTemp, num);       // 注意調(diào)用函數(shù)所需要的真實(shí)數(shù)據(jù)長(zhǎng)度; 如果目標(biāo)需要以0作結(jié)尾判斷,需num+1:字符串以0結(jié)尾,即多發(fā)一個(gè):0
}

#endif





//  printf   //
/******************************************************************************
 * 功  能: printf函數(shù)支持代碼
 *         【特別注意】加入以下代碼, 使用printf函數(shù)時(shí), 不再需要選擇use MicroLIB
 * 參  數(shù):
 * 返回值:
 * 備  注: 最后修改_2020年07月15日
 ******************************************************************************/
//加入以下代碼,支持printf函數(shù),而不需要選擇use MicroLIB
//#pragma import(__use_no_semihosting)
//struct __FILE
//{
//    int handle;
//};                     // 標(biāo)準(zhǔn)庫(kù)需要的支持函數(shù)
//FILE __stdout;         // FILE 在stdio.h文件
void _sys_exit(int x)
{
    x = x;             // 定義_sys_exit()以避免使用半主機(jī)模式
}



//重定向 c 庫(kù)函數(shù) printf 到串口,重定向后可使用 printf 函數(shù)
int fputc(int ch, FILE *f)
{  /* 發(fā)送一個(gè)字節(jié)數(shù)據(jù)到串口 */
USART_SendData(DEBUG_USARTx, (uint8_t) ch);
 /* 等待發(fā)送完畢 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
 return (ch);
 }

 ///重定向 c 庫(kù)函數(shù) scanf 到串口,重寫(xiě)向后可使用 scanf、getchar 等函數(shù)
 int fgetc(FILE *f)
 {
 /* 等待串口輸入數(shù)據(jù) */
 while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);

 return (int)USART_ReceiveData(DEBUG_USARTx);
 }




///*
//函數(shù)名:USART3中斷服務(wù)函數(shù)
//功能:  接收數(shù)據(jù)
//注意:接收數(shù)據(jù)長(zhǎng)度可調(diào):RXCOUNT
//*/
//void USART3_IRQHandler(void)
//{
//	u8 temp;
//	
//  if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
//  {
//		USART_ClearITPendingBit(USART3,USART_IT_RXNE);
//		temp = USART_ReceiveData(USART3);
//		if(temp == '\n' || RXCOUNT == 20)   //判斷是否接收到一個(gè)完整字符
//		{
//			RXCOUNT = 0;
//			RXOVER =1;    //接收數(shù)據(jù)完成標(biāo)志位置1
//			USART_ITConfig(USART3,USART_IT_RXNE,DISABLE);//失能串口接收中斷標(biāo)志	
//		}
//		else
//		{
//			RXBUF[RXCOUNT] = temp;   //依次存放到數(shù)組中
//			RXCOUNT++;		           //字符長(zhǎng)度變化
//		}
//	}
//}

main.c

/**
  ******************************************************************************
  * @file    main.c
  * @author  fire
  * @version V1.0
  * @date    2013-xx-xx
  * @brief   rtc 測(cè)試,顯示時(shí)間格式為: xx:xx:xx
  ******************************************************************************
  * @attention
  *
  * 實(shí)驗(yàn)平臺(tái):野火 F103-指南者 STM32 開(kāi)發(fā)板 
  * 論壇    :http://www.firebbs.cn
  * 淘寶    :https://fire-stm32.taobao.com
  *
  ******************************************************************************
  */
	
#include "stm32f10x.h"
#include "./usart/bsp_usart.h"
#include "./rtc/bsp_rtc.h"
#include "./lcd/bsp_ili9341_lcd.h"
#include "./key/bsp_key.h"  
#include "./DTH11/DTH11.h"
#include "./Led/bsp_led.h"
#include "./syn6288/syn6288.h"
//變量聲明
u8 RXBUF[20];       //串口存儲(chǔ)數(shù)組
u8 RXOVER=0;        //串口接收標(biāo)志位
u8 RXCOUNT=0;       //串口計(jì)數(shù)變量  
u8 i;               //清空數(shù)組變量



//時(shí)間更新函數(shù)
void 											Update_FrameShow										(void);

//表盤(pán)框架繪制
void 											DrawFixed_Frame										(void);
void 											DrawExcel												(void);
void 											DrawCongratulate										(void);
void 											DrawTimeFrame											(void);
void 											DrawExternal_Environmentz							(void);
void 											DrawWish													(void);
//語(yǔ)音處理函數(shù)
void 											USART_Deal												(void);

// N = 2^32/365/24/60/60 = 136 年

/*時(shí)間結(jié)構(gòu)體,默認(rèn)時(shí)間2024-03-02 03:20:10*/
struct rtc_time systmtime=
{
10,20,3,1,2,2024,4
};

extern __IO uint32_t TimeDisplay ;
//溫度參數(shù)

/**
  * @brief  主函數(shù)
  * @param  無(wú)  
  * @retval 無(wú)
  */
int main()
{		
	
//可使用該宏設(shè)置是否使用液晶顯示
#ifdef  USE_LCD_DISPLAY
	
		ILI9341_Init ();         //LCD 初始化
		LCD_SetFont(&Font8x16);
		LCD_SetColors(CurrentTextColor,CurrentBackColor);

		ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH);	/* 清屏,顯示全黑 */
		
		DrawFixed_Frame();//繪制固定物


#endif
		//串口部分
	   USART_Config();		
		LED_Configuration();//LED配置
		SYN6288_Init(USART2);                             // 初始化; USART2-PA2
		USART3_Init(9600);											//LD3320串口初始化
		
		Key_GPIO_Config();

		/* 配置RTC秒中斷優(yōu)先級(jí) */
	  RTC_NVIC_Config();
	  RTC_CheckAndConfig(&systmtime);
	  DHT11_Init();  //初始化溫度傳感器引腳
	  
	  SYN6288_Say("已開(kāi)燈");//Syn6288測(cè)試
	  //Temperuture_Get();
	  while (1)
	  {
	    /* 每過(guò)1s 更新一次時(shí)間*/
	    if (TimeDisplay == 1)
	    {
				/* 當(dāng)前時(shí)間 */
	      Time_Display( RTC_GetCounter(),&systmtime); 
			//Time_Display1( RTC_GetCounter(),Temperature_Get(),&systmtime); //當(dāng)加入溫度獲取時(shí),溫度獲取

	      TimeDisplay = 0;
	    }
			
			//按下按鍵,通過(guò)串口修改時(shí)間
			if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON  )
			{
				struct rtc_time set_time;

				/*使用串口接收設(shè)置的時(shí)間,輸入數(shù)字時(shí)注意末尾要加回車(chē)*/
				Time_Regulate_Get(&set_time);
				/*用接收到的時(shí)間設(shè)置RTC*/
				Time_Adjust(&set_time);
				
				//向備份寄存器寫(xiě)入標(biāo)志
				BKP_WriteBackupRegister(RTC_BKP_DRX, RTC_BKP_DATA);

			} 
		  USART_Deal();
	  }
}

/**************************************表盤(pán)框架繪制*****************************************/

/*
函數(shù)功能: 繪制所有固定物
*/
void DrawFixed_Frame(void)
{
DrawExcel();
DrawCongratulate();
DrawTimeFrame();
DrawExternal_Environmentz();
DrawWish();
}

/*
函數(shù)功能: 繪制表格
*/
void DrawExcel(void)
{
ILI9341_DrawRectangle ( 0, 0, 240, 320, 0);
ILI9341_DrawLine(0,136,50,136);
ILI9341_DrawLine(185,136,240,136);
ILI9341_DrawLine(0,180,240,180);
ILI9341_DrawLine(0,200,240,200);
ILI9341_DrawLine(48,200,48,320);
ILI9341_DrawLine(240-48,200,240-48,320);
}
/*
函數(shù)功能: 繪制時(shí)鐘表盤(pán)框架
*/
void DrawTimeFrame(void)
{
	uint8_t i;
	ILI9341_DrawCircle(RoundCenter_X,RoundCenter_Y,RoundRadius,0);//畫(huà)外圓
	ILI9341_DrawCircle(RoundCenter_X,RoundCenter_Y,RoundCenter,1); //畫(huà)中心圓
	//畫(huà)刻度
	for(i=0;i<60;i++)
	{
		if(i%5==0)
		{//繪制圓大間距
		ILI9341_DrawAngleLine(RoundCenter_X,RoundCenter_Y,6*i,RoundRadius-6,RoundRadius,RoundInterval_Color);
		}
		else
		{//繪制圓小間距
		ILI9341_DrawAngleLine(RoundCenter_X,RoundCenter_Y,6*i,RoundRadius-3,RoundRadius,RoundInterval_Color);
		}
		
	}
	//OLED_WriteGRAM();  //刷新數(shù)據(jù)到OLED屏幕
}
/*
函數(shù)功能: 繪制龍年大吉
*/
void DrawCongratulate(void)
{
		ILI9341_DisplayStringEx(10,10,32,32,(uint8_t *)"龍",0);
		ILI9341_DisplayStringEx(240-32-10,10,32,32,(uint8_t *)"年",0);
		ILI9341_DisplayStringEx(10,3*32,32,32,(uint8_t *)"大",0);
		ILI9341_DisplayStringEx(240-32-10,3*32,32,32,(uint8_t *)"吉",0);
}

/*
函數(shù)功能: 繪制外部環(huán)境
*/
void DrawExternal_Environmentz(void)
{
ILI9341_DisplayStringEx(20,144,16,16,(uint8_t *)"天氣:多云",0);//也可后續(xù)添加天氣檢測(cè)設(shè)備配置
ILI9341_DisplayStringEx(120,144,16,16,(uint8_t *)"溫度:",0);//其他添加可仿照溫度配置
ILI9341_DisplayStringEx(20,160,16,16,(uint8_t *)"位置:貴陽(yáng)",0);//也可后續(xù)添加定位設(shè)備配置
ILI9341_DisplayStringEx(120,160,16,16,(uint8_t *)"濕度:",0);//也可后續(xù)添加空氣檢測(cè)設(shè)備配置

}
/*
函數(shù)功能: 繪制祝愿
*/
void DrawWish(void)
{
ILI9341_DisplayStringEx(12,210,24,24,(uint8_t *)"宜",0);
ILI9341_DisplayStringEx(204,210,24,24,(uint8_t *)"忌",0);

ILI9341_DisplayStringEx_YDir(8,240,16,16,(uint8_t *)"搞錢(qián)",0);
ILI9341_DisplayStringEx_YDir(28,240,16,16,(uint8_t *)"畢業(yè)設(shè)計(jì)",0);
ILI9341_DisplayStringEx_YDir(200,240,16,16,(uint8_t *)"晚睡晚起",0);
ILI9341_DisplayStringEx_YDir(220,240,16,16,(uint8_t *)"打游戲",0);

ILI9341_DisplayStringEx(52,210,24,24,(uint8_t *)"等待開(kāi)發(fā)",0);
}




/**************************************表盤(pán)框架繪制結(jié)束*****************************************/
/*
函數(shù)功能: 更新時(shí)間框架顯示,在RTC中斷里調(diào)用
*/
void Update_FrameShow(void)
{
	/*1. 繪制秒針、分針、時(shí)針*/
	 //畫(huà)秒針
	ILI9341_DrawAngleLine2(RoundCenter_X,RoundCenter_Y,systmtime.tm_sec*6-6-90,RoundCenter,RoundSecondHand,0);//清除之前的秒針
	ILI9341_DrawAngleLine(RoundCenter_X,RoundCenter_Y,systmtime.tm_sec*6-90,RoundCenter,RoundSecondHand,RoundSecondHand_Color);
	//畫(huà)分針
	ILI9341_DrawAngleLine2(RoundCenter_X,RoundCenter_Y,systmtime.tm_min*6-6-90,RoundCenter,RoundMiuiteHand,0);
	ILI9341_DrawAngleLine(RoundCenter_X,RoundCenter_Y,systmtime.tm_min*6-90,RoundCenter,RoundMiuiteHand,RoundMiuiteHand_Color);
	//畫(huà)時(shí)針	
	ILI9341_DrawAngleLine2(RoundCenter_X,RoundCenter_Y,systmtime.tm_hour*30-30-90,RoundCenter,RoundHourHand,0);
	ILI9341_DrawAngleLine(RoundCenter_X,RoundCenter_Y,systmtime.tm_hour*30-90,RoundCenter,RoundHourHand,RoundHourHand_Color);
	
}

/***********************************END OF FILE*********************************/

//串口處理函數(shù)
void USART_Deal(void)
{
		if(RXOVER)
		{
			RXOVER = 0;    //清除接收標(biāo)志位
			switch(RXBUF[0]-48)
			{
				case   1:GPIO_ResetBits(GPIOB,GPIO_Pin_0);   //點(diǎn)亮小燈
							SYN6288_Say("已開(kāi)燈");

								 break;
				
				case   2:GPIO_SetBits(GPIOB,GPIO_Pin_0); //熄滅小燈
							SYN6288_Say("已關(guān)燈");

								 break;	
				default: break;			
			}
			USART3_SendString(RXBUF);    //發(fā)送給pc機(jī)上面打印顯示			
			for(i=0;i<20;i++)            //將已接收數(shù)據(jù)的數(shù)組清空:共20個(gè)字符長(zhǎng)度
			{
				 RXBUF[i] = 0;          	 //重置數(shù)據(jù)緩存區(qū)
			}
			USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);//始能串口接收 
		}
}

基于stm32F103的座面聲控臺(tái)燈,stm32,嵌入式硬件,單片機(jī)

液晶顯示指針式時(shí)鐘核心代碼在上文已經(jīng)放出,本文核心代碼如上,本人撰寫(xiě)代碼也需要時(shí)間,如需要全部代碼或者僅需語(yǔ)音部分代碼請(qǐng)私信我,感謝大家理解。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-861909.html

到了這里,關(guān)于基于stm32F103的座面聲控臺(tái)燈的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀(guān)點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 基于STM32F103HAL庫(kù)的聲音定位系統(tǒng)

    基于STM32F103HAL庫(kù)的聲音定位系統(tǒng)

    這是一道學(xué)校出的電賽題目,要求在100*100cm的平面上實(shí)現(xiàn)定位實(shí)現(xiàn)聲音定位。由于一米太大了,我們就做了40cm的,下面的講解我按照40厘米的寫(xiě)。用到的處理器是stm32f103c8t6接下來(lái)分享一下調(diào)試心得。 硬件部分需要制作發(fā)聲裝置和接收裝置,詳細(xì)可以

    2024年02月14日
    瀏覽(29)
  • STM32--基于STM32F103的MAX30102心率血氧測(cè)量

    STM32--基于STM32F103的MAX30102心率血氧測(cè)量

    本文介紹基于STM32F103ZET6+MAX30102心率血氧測(cè)量+0.96寸OLED(7針)顯示(完整程序代碼見(jiàn)文末鏈接) 一、簡(jiǎn)介 MAX30102是一個(gè)集成的脈搏血氧儀和心率監(jiān)測(cè)儀生物傳感器的模塊。它集成了一個(gè)紅光LED和一個(gè)紅外光LED、光電檢測(cè)器、光器件,以及帶環(huán)境光抑制的低噪聲電子電路。 MA

    2024年01月16日
    瀏覽(35)
  • stm32f103基于pid的藍(lán)牙循跡小車(chē)

    stm32f103基于pid的藍(lán)牙循跡小車(chē)

    目錄 前言 一、霍爾編碼器以及定時(shí)器計(jì)數(shù)原理 二、使用pwm占空比對(duì)電機(jī)速度進(jìn)行控制 三、使用systick的中斷函數(shù)進(jìn)行pid和速度的計(jì)算,還有oled的顯示 四、常用的測(cè)速方法: ?五、pid原理 六、oled的實(shí)現(xiàn) 七、藍(lán)牙通信 八、3路循跡模塊 總結(jié) ? 經(jīng)過(guò)一個(gè)月對(duì)stm32的學(xué)習(xí),終于完

    2024年02月16日
    瀏覽(34)
  • 基于STM32F103的PWM電機(jī)驅(qū)動(dòng)A4950

    基于STM32F103的PWM電機(jī)驅(qū)動(dòng)A4950

    A4950的峰值輸出電流可達(dá)±3.5 A,工作電壓為7.6~40v。 優(yōu)點(diǎn):相對(duì)于L298N模塊控制2個(gè)電機(jī)正反轉(zhuǎn)僅需要4個(gè)I/O口,體積小,發(fā)熱低。 缺點(diǎn):需要2個(gè)PWM引腳才能控制正反轉(zhuǎn),所以控制2個(gè)電機(jī)需要4PWM引腳,會(huì)使用STM32F103芯片一個(gè)定時(shí)器的全部PWM通道。 A4950模塊是靠輸入2路的PWM占空

    2024年02月04日
    瀏覽(30)
  • 基于STM32F103——SIM900A發(fā)送短信+串口打印

    基于STM32F103——SIM900A發(fā)送短信+串口打印

    最近用STM32F103做一個(gè)智能門(mén)鎖小玩意,密碼輸入錯(cuò)誤次數(shù)多進(jìn)行驗(yàn)證碼解鎖,這里我采用SIM900A來(lái)通過(guò)發(fā)送短信輸入驗(yàn)證碼進(jìn)行解鎖。就是簡(jiǎn)單的了解了一下在這里也單獨(dú)的寫(xiě)寫(xiě)這個(gè)SIM900A的一寫(xiě)筆記。 。。。。。。還是直接進(jìn)入主題吧 SIM900A是可以AT指令操作的,所以一般我拿

    2023年04月12日
    瀏覽(33)
  • STM32項(xiàng)目設(shè)計(jì):基于stm32f103c8t6智能電梯系統(tǒng)

    STM32項(xiàng)目設(shè)計(jì):基于stm32f103c8t6智能電梯系統(tǒng)

    資料鏈接:待更新~ 嗶哩嗶哩視頻鏈接:https://www.bilibili.com/video/BV17D4y1V7HG/?vd_source=e5082ef80535e952b2a4301746491be0(bilibili:化作塵my) 資料鏈接:https://pan.baidu.com/s/1qObK7KBl50RmFrAtoX12kw 提取碼:iih4 實(shí)物鏈接:https://m.tb.cn/h.5h5mDXI?tk=MdxLWYHgKnz CZ0001 1、OLED顯示當(dāng)前樓層、目標(biāo)樓層等信息

    2024年02月03日
    瀏覽(39)
  • 基于STM32F103——XGZP6847D壓力傳感器+串口打印

    基于STM32F103——XGZP6847D壓力傳感器+串口打印

    XGZP6847D 型壓力傳感器尺寸小、易安裝,廣泛用于醫(yī)療電子、汽車(chē)電子、消費(fèi)電子、運(yùn)動(dòng)健身器材、 物聯(lián)網(wǎng)等領(lǐng)域 Reg0x30(測(cè)量命令寄存器) Measurement_control2:0( 工作模式 ) 010b ,組合采集模式(一次溫度采集后立即進(jìn)行一次傳感器壓力信號(hào)采集)。 011b ,休眠工作模式(定期的執(zhí)

    2023年04月24日
    瀏覽(36)
  • 【基于STM32F103C8T6的智能風(fēng)扇控制】

    【基于STM32F103C8T6的智能風(fēng)扇控制】

    本次分享的是基于STM32F103的智能風(fēng)扇的制作,相關(guān)的硬件和部分源碼可看下面哦,需要成品的可私(創(chuàng)作不易,拒絕白嫖) 喜歡就給小殷一個(gè)關(guān)注和點(diǎn)贊吧 演示視頻鏈接 1、按鍵模式下通過(guò)按鍵進(jìn)行風(fēng)扇檔數(shù)改變一共設(shè)置為4檔 2、自動(dòng)模式下根據(jù)環(huán)境溫度而改變溫度的轉(zhuǎn)速和

    2024年02月12日
    瀏覽(34)
  • [STM32F103C8T6]基于stm32的循跡,跟隨,避障智能小車(chē)

    [STM32F103C8T6]基于stm32的循跡,跟隨,避障智能小車(chē)

    目錄 1.小車(chē)驅(qū)動(dòng)主要是通過(guò)L9110S模塊來(lái)驅(qū)動(dòng)電機(jī) motor.c 2.我們可以加入串口控制電機(jī)驅(qū)動(dòng)(重寫(xiě)串口接收回調(diào)函數(shù),和重定向printf) Uart.c main.c? 3.點(diǎn)動(dòng)功能 uart.c main.c 為什么使用的是HAL_Delay()要設(shè)置滴答定時(shí)器的中斷優(yōu)先級(jí)呢? 4.小車(chē)PWM調(diào)速,? 6.跟隨功能 7.避障功能 超聲波測(cè)距

    2024年02月13日
    瀏覽(43)
  • 基于STM32F103的紅外循跡 超聲波避障小車(chē)

    單片機(jī):stm32f103 傳感器:普通紅外(我用了4個(gè)) 超聲波:HC-SR04 舵機(jī):SG90 目標(biāo):可以循黑線(xiàn)(十字直行)、并避障 如果硬件配置和我一樣以下代碼可直接使用,用我配置的引腳即可。 親測(cè)好用。 復(fù)制代碼的同時(shí)請(qǐng)點(diǎn)個(gè)贊,多謝! .c .h .c .h .c .h .c .h 我的主函數(shù)有些啰嗦,

    2024年02月05日
    瀏覽(31)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包