日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > > 嵌入式案例Show
[導(dǎo)讀]硬件設(shè)計(jì)完成,下面就要進(jìn)行軟件開(kāi)發(fā)了,本篇主要介紹串口模塊、按鍵模塊的初始化及功能測(cè)試。

文 | 嵌Sir

硬件設(shè)計(jì)完成,下面就要進(jìn)行軟件開(kāi)發(fā)了,本篇主要介紹串口模塊、按鍵模塊的初始化及功能測(cè)試。
程序開(kāi)發(fā)前我習(xí)慣查看原理圖把所有外設(shè)對(duì)應(yīng)的管腳全部列出來(lái),方便后續(xù)開(kāi)發(fā)時(shí)查看。

01

串口模塊

串口管腳配置如下:

查看芯片規(guī)格書(shū)可知 PA9和PA10的默認(rèn)功能為串口1,PD8和PD9需要重定義為串口3使用。
管腳定義:

 #define UART1_TXD_GPIO_PORT GPIOA #define UART1_TXD_GPIO_CLK RCC_APB2Periph_GPIOA #define UART1_TXD_GPIO_PIN GPIO_Pin_9 #define UART1_TXD_GPIO_MODE GPIO_Mode_AF_PP  #define UART1_RXD_GPIO_PORT GPIOA #define UART1_RXD_GPIO_CLK RCC_APB2Periph_GPIOA #define UART1_RXD_GPIO_PIN GPIO_Pin_10 #define UART1_RXD_GPIO_MODE GPIO_Mode_IN_FLOATING #define UART3_TXD_GPIO_PORT GPIOD#define UART3_TXD_GPIO_CLK RCC_APB2Periph_GPIOD#define UART3_TXD_GPIO_PIN GPIO_Pin_8#define UART3_TXD_GPIO_MODE GPIO_Mode_AF_PP #define UART3_RXD_GPIO_PORT GPIOD#define UART3_RXD_GPIO_CLK RCC_APB2Periph_GPIOD#define UART3_RXD_GPIO_PIN GPIO_Pin_9#define UART3_RXD_GPIO_MODE GPIO_Mode_IPU 

本文使用中斷方式接收和發(fā)送,串口和串口中斷初始化代碼如下:

GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure; //UART1 管腳配置:時(shí)鐘、模式 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); GPIO_InitStructure.GPIO_Pin = UART1_RXD_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = UART1_RXD_GPIO_MODE; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(UART1_RXD_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = UART1_TXD_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = UART1_TXD_GPIO_MODE; GPIO_Init(UART1_TXD_GPIO_PORT, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); //配置nvic向量表NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* Enable the USARTy Interrupt */NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);  /* Enable USART1 Receive and Transmit interrupts */USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //一開(kāi)始就是要關(guān)閉 /* Enable USART */USART_Cmd(USART1, ENABLE);  gb_needDealUart1Data = 0;uart1DelayTimer = 0; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);//UART3 管腳配置:時(shí)鐘、模式 GPIO_InitStructure.GPIO_Pin = UART3_RXD_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = UART3_RXD_GPIO_MODE; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(UART3_RXD_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = UART3_TXD_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = UART3_TXD_GPIO_MODE; GPIO_Init(UART3_TXD_GPIO_PORT, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART3, &USART_InitStructure);   //配置nvic向量表NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* Enable the USARTy Interrupt */NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);  /* Enable USART3 Receive and Transmit interrupts */USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);USART_ITConfig(USART3, USART_IT_TXE, DISABLE); //一開(kāi)始就是要關(guān)閉 /* Enable USART */USART_Cmd(USART3, ENABLE);  gb_needDealUart3Data = 0; 

初始化的時(shí)候別忘記串口3的remap。

GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);

串口收發(fā)中斷處理,以串口3為例:

void USART3_IRQHandler(void){ u8 d;  if (USART_GetFlagStatus(USART3, USART_FLAG_RXNE)) { /* Read one byte from the receive data register */ d = USART_ReceiveData(USART3); uart3infifo_DataIn(d);  uart3DelayTimer = UART3_DATA_DELAY; gb_needDealUart3Data = 0; } else if (USART_GetFlagStatus(USART3, USART_FLAG_TXE)) {  if (uart3outfifo_count > 0) { /* Write one b yte to the transmit data register */ USART_SendData(USART3, uart3outfifo_DataOut()); //順便清除flag_TXE }  else { /* Disable the USARTy Transmit interrupt */ USART_ITConfig(USART3, USART_IT_TXE, DISABLE); //實(shí)際上,發(fā)送為空的標(biāo)志還在,只是關(guān)閉中斷 }  }} 

串口中斷中收到數(shù)據(jù)先進(jìn)FIFO,等一個(gè)數(shù)據(jù)包接收完后進(jìn)入處理。需要發(fā)送數(shù)據(jù),把數(shù)據(jù)填入fifo,中斷里自動(dòng)發(fā)送。我一般都是采用這種中斷加fifo的收發(fā)方式。中斷就像是后臺(tái)操作一樣,在主程序的流程中,不用刻意去關(guān)注中斷方式發(fā)送了沒(méi)有,何時(shí)接收等,而查詢方式是在主程序流程中不斷查看是否接收到了數(shù)據(jù),一般用while不斷循環(huán)查看。中斷方式可以更高效利用CPU ,節(jié)省CPU的時(shí)間,查詢就會(huì)增加CPU負(fù)擔(dān)。

02

按鍵模塊

查看原理圖,矩陣按鍵管腳如下:

矩陣鍵盤(pán)管腳定義及初始化:

#define ROW0_GPIO_PORT GPIOE#define ROW0_GPIO_PIN GPIO_Pin_8#define ROW0_GPIO_MODE GPIO_Mode_IPU #define ROW1_GPIO_PORT GPIOE#define ROW1_GPIO_PIN GPIO_Pin_9#define ROW1_GPIO_MODE GPIO_Mode_IPU  #define COL0_GPIO_PORT GPIOE#define COL0_GPIO_PIN GPIO_Pin_10#define COL0_GPIO_MODE GPIO_Mode_Out_PP #define COL1_GPIO_PORT GPIOE#define COL1_GPIO_PIN GPIO_Pin_11#define COL1_GPIO_MODE GPIO_Mode_Out_PP #define SetRow0() GPIO_SetBits(ROW0_GPIO_PORT, ROW0_GPIO_PIN)#define ResetRow0() GPIO_ResetBits(ROW0_GPIO_PORT, ROW0_GPIO_PIN)#define ReadRow0() GPIO_ReadInputDataBit(ROW0_GPIO_PORT,ROW0_GPIO_PIN) #define SetRow1() GPIO_SetBits(ROW1_GPIO_PORT, ROW1_GPIO_PIN)#define ResetRow1() GPIO_ResetBits(ROW1_GPIO_PORT, ROW1_GPIO_PIN)#define ReadRow1() GPIO_ReadInputDataBit(ROW1_GPIO_PORT,ROW1_GPIO_PIN) #define SetCOL0() GPIO_SetBits(COL0_GPIO_PORT, COL0_GPIO_PIN)#define ResetCOL0() GPIO_ResetBits(COL0_GPIO_PORT, COL0_GPIO_PIN)#define ReadCOL0() GPIO_ReadInputDataBit(COL0_GPIO_PORT,COL0_GPIO_PIN) #define SetCOL1() GPIO_SetBits(COL1_GPIO_PORT, COL1_GPIO_PIN)#define ResetCOL1() GPIO_ResetBits(COL1_GPIO_PORT, COL1_GPIO_PIN)#define ReadCOL1() GPIO_ReadInputDataBit(COL1_GPIO_PORT,COL1_GPIO_PIN) 
void keyboard_Init(void){  GPIO_InitTypeDef GPIO_InitStructure;  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;   GPIO_InitStructure.GPIO_Pin = ROW0_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = ROW0_GPIO_MODE;  GPIO_Init(ROW0_GPIO_PORT, &GPIO_InitStructure);  GPIO_InitStructure.GPIO_Pin = ROW1_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = ROW1_GPIO_MODE;  GPIO_Init(ROW1_GPIO_PORT, &GPIO_InitStructure);  GPIO_InitStructure.GPIO_Pin = COL0_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = COL0_GPIO_MODE;  GPIO_Init(COL0_GPIO_PORT, &GPIO_InitStructure); SetCol(0);  GPIO_InitStructure.GPIO_Pin = COL1_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = COL1_GPIO_MODE;  GPIO_Init(COL1_GPIO_PORT, &GPIO_InitStructure); SetCol(1);} 

矩陣鍵盤(pán)鍵值讀?。?

u8 keyboard_GetCurrentKey( void){ u8 kbVal; u8 rowIndex; u8 colIndex;  kbVal = KEY_noKey;  for(colIndex = 0; colIndex < COL_NUM; colIndex ++)//按列查詢 {  ClrCol(colIndex);//列線置低 for (rowIndex=0; rowIndex < ROW_NUM; rowIndex ++)//按行掃描 { if (!RowVal(rowIndex))//讀當(dāng)前行電平 { kbVal = KEY_VAL[rowIndex][colIndex];//有值返回,并跳出循環(huán) break; } } SetCol(colIndex);//列線置高 if (kbVal != KEY_noKey) { break; } } return(kbVal);} 


可以在主函數(shù)中輪詢鍵值進(jìn)行處理,也可以在定時(shí)器中斷中輪詢鍵值。在中斷中的不要寫(xiě)耗時(shí)操作或者加延時(shí)。在定時(shí)中斷輪詢鍵值一般也是配合fifo使用。代碼如下:

//2ms定時(shí)器void TIM5_IRQHandler(void){ if (TIM_GetFlagStatus(TIM5, TIM_IT_Update)) { TIM_ClearFlag(TIM5, TIM_IT_Update); ScanKeyDown();//處理按鍵中斷 }}
void ScanKeyDown(void){ g_keyPara.currentLcdKey = keyboard_GetCurrentKey(); //讀取鍵值 g_keyPara.keyFlag <<= 1; if(g_keyPara.currentLcdKey != KEY_noKey) { g_keyPara.keyFlag ++; }  if (!g_keyPara.longLcdKeyFlag)//長(zhǎng)按和短按處理 和短按的去抖處理 { if (g_keyPara.currentLcdKey == KEY_noKey) { if ((g_keyPara.shortLcdKeyTimer == 0)&&g_keyPara.shortLcdKey != 0) {  fifo_DataIn(KB_FIFO,g_keyPara.shortLcdKey); //鍵值進(jìn)fifo隊(duì)列等待處理 } g_keyPara.enterLongLcdKeyTimer = ENTER_LONG_KEY_TIME; g_keyPara.shortLcdKeyTimer = SHORT_KEY_TIME; } else { if (g_keyPara.shortLcdKeyTimer > 0) { g_keyPara.shortLcdKeyTimer --; if (g_keyPara.shortLcdKeyTimer == 0) { g_keyPara.shortLcdKey = g_keyPara.currentLcdKey; } }  if(g_keyPara.enterLongLcdKeyTimer > 0) { g_keyPara.enterLongLcdKeyTimer --; if (g_keyPara.enterLongLcdKeyTimer == 0) { g_keyPara.longLcdKeyIntervalTimer = LONG_KEY_INTERVAL_TIME; g_keyPara.longLcdKeyFlag = 1; g_keyPara.longLcdKey = g_keyPara.currentLcdKey;   fifo_DataIn(KB_FIFO,g_keyPara.longLcdKey+0x20);//鍵值進(jìn)fifo隊(duì)列等待處理 } } } } else { if (g_keyPara.currentLcdKey == g_keyPara.longLcdKey) { if (g_keyPara.longLcdKeyIntervalTimer > 0) { g_keyPara.longLcdKeyIntervalTimer --; if (g_keyPara.longLcdKeyIntervalTimer == 0) { fifo_DataIn(KB_FIFO,g_keyPara.longLcdKey+0x20); //鍵值進(jìn)fifo隊(duì)列等待處理  } } } else { g_keyPara.longLcdKeyFlag = 0; g_keyPara.longLcdKey = KEY_noKey; g_keyPara.shortLcdKey = KEY_noKey; g_keyPara.shortLcdKeyTimer = SHORT_KEY_TIME; g_keyPara.enterLongLcdKeyTimer = ENTER_LONG_KEY_TIME; g_keyPara.longLcdKeyIntervalTimer = LONG_KEY_INTERVAL_TIME; } }}

/ The End /

本文主要介紹了串口模塊和矩陣鍵盤(pán)模塊的管腳配置和初始化,并簡(jiǎn)要介紹了各模塊的中斷使用方法。如有疑問(wèn),歡迎留言討論。

本文由【嵌入式案例Show】原創(chuàng)出品,未經(jīng)許可,請(qǐng)勿轉(zhuǎn)載


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過(guò)流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問(wèn)題卻十分常見(jiàn),不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問(wèn)題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(chē)(EV)作為新能源汽車(chē)的重要代表,正逐漸成為全球汽車(chē)產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車(chē)的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車(chē)的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車(chē) 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車(chē)場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問(wèn)題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周?chē)娮釉O(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來(lái)解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開(kāi)關(guān)電源具有效率高的特性,而且開(kāi)關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開(kāi)關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉