当前位置:首页 > > 嵌入式案例Show
[导读]硬件设计完成,下面就要进行软件开发了,本篇主要介绍串口模块、按键模块的初始化及功能测试。

文 | 嵌Sir

硬件设计完成,下面就要进行软件开发了,本篇主要介绍串口模块、按键模块的初始化及功能测试。
程序开发前我习惯查看原理图把所有外设对应的管脚全部列出来,方便后续开发时查看。

01

串口模块

串口管脚配置如下:

查看芯片规格书可知 PA9和PA10的默认功能为串口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 

本文使用中断方式接收和发送,串口和串口中断初始化代码如下:

GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure; //UART1 管脚配置:时钟、模式 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); //一开始就是要关闭 /* Enable USART */USART_Cmd(USART1, ENABLE);  gb_needDealUart1Data = 0;uart1DelayTimer = 0; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);//UART3 管脚配置:时钟、模式 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); //一开始就是要关闭 /* Enable USART */USART_Cmd(USART3, ENABLE);  gb_needDealUart3Data = 0; 

初始化的时候别忘记串口3的remap。

GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);

串口收发中断处理,以串口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); //实际上,发送为空的标志还在,只是关闭中断 }  }} 

串口中断中收到数据先进FIFO,等一个数据包接收完后进入处理。需要发送数据,把数据填入fifo,中断里自动发送。我一般都是采用这种中断加fifo的收发方式。中断就像是后台操作一样,在主程序的流程中,不用刻意去关注中断方式发送了没有,何时接收等,而查询方式是在主程序流程中不断查看是否接收到了数据,一般用while不断循环查看。中断方式可以更高效利用CPU ,节省CPU的时间,查询就会增加CPU负担。

02

按键模块

查看原理图,矩阵按键管脚如下:

矩阵键盘管脚定义及初始化:

#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);} 

矩阵键盘键值读取:

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))//读当前行电平 { kbVal = KEY_VAL[rowIndex][colIndex];//有值返回,并跳出循环 break; } } SetCol(colIndex);//列线置高 if (kbVal != KEY_noKey) { break; } } return(kbVal);} 


可以在主函数中轮询键值进行处理,也可以在定时器中断中轮询键值。在中断中的不要写耗时操作或者加延时。在定时中断轮询键值一般也是配合fifo使用。代码如下:

//2ms定时器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)//长按和短按处理 和短按的去抖处理 { if (g_keyPara.currentLcdKey == KEY_noKey) { if ((g_keyPara.shortLcdKeyTimer == 0)&&g_keyPara.shortLcdKey != 0) {  fifo_DataIn(KB_FIFO,g_keyPara.shortLcdKey); //键值进fifo队列等待处理 } 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);//键值进fifo队列等待处理 } } } } 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); //键值进fifo队列等待处理  } } } 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 /

本文主要介绍了串口模块和矩阵键盘模块的管脚配置和初始化,并简要介绍了各模块的中断使用方法。如有疑问,欢迎留言讨论。

本文由【嵌入式案例Show】原创出品,未经许可,请勿转载


免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

特朗普集团近日取消了其新推出的T1智能手机“将在美国制造”的宣传标语,此举源于外界对这款手机能否以当前定价在美国本土生产的质疑。

关键字: 特朗普 苹果 AI

美国总统特朗普在公开场合表示,他已要求苹果公司CEO蒂姆·库克停止在印度建厂,矛头直指该公司生产多元化的计划。

关键字: 特朗普 苹果 AI

4月10日消息,据媒体报道,美国总统特朗普宣布,美国对部分贸易伙伴暂停90天执行新关税政策,同时对中国的关税提高到125%,该消息公布后苹果股价飙升了15%。这次反弹使苹果市值增加了4000多亿美元,目前苹果市值接近3万...

关键字: 特朗普 AI 人工智能 特斯拉

3月25日消息,据报道,当地时间3月20日,美国总统特朗普在社交媒体平台“真实社交”上发文写道:“那些被抓到破坏特斯拉的人,将有很大可能被判入狱长达20年,这包括资助(破坏特斯拉汽车)者,我们正在寻找你。”

关键字: 特朗普 AI 人工智能 特斯拉

1月22日消息,刚刚,新任美国总统特朗普放出重磅消息,将全力支持美国AI发展。

关键字: 特朗普 AI 人工智能

特朗普先生有两件事一定会载入史册,一个是筑墙,一个是挖坑。在美墨边境筑墙的口号确保边境安全,降低因非法移民引起的犯罪率过高问题;在中美科技产业之间挖坑的口号也是安全,美国企业不得使用对美国国家安全构成威胁的电信设备,总统...

关键字: 特朗普 孤立主义 科技产业

据路透社1月17日消息显示,知情人士透露,特朗普已通知英特尔、铠侠在内的几家华为供应商,将要撤销其对华为的出货的部分许可证,同时将拒绝其他数十个向华为供货的申请。据透露,共有4家公司的8份许可被撤销。另外,相关公司收到撤...

关键字: 华为 芯片 特朗普

曾在2018年时被美国总统特朗普称作“世界第八奇迹”的富士康集团在美国威斯康星州投资建设的LCD显示屏工厂项目,如今却因为富士康将项目大幅缩水并拒绝签订新的合同而陷入了僵局。这也导致富士康无法从当地政府那里获得约40亿美...

关键字: 特朗普 富士康

今年5月,因自己发布的推文被贴上“无确凿依据”标签而与推特发生激烈争执后,美国总统特朗普签署了一项行政令,下令要求重审《通信规范法》第230条。

关键字: 谷歌 facebook 特朗普

众所周知,寄往白宫的所有邮件在到达白宫之前都会在他地进行分类和筛选。9月19日,根据美国相关执法官员的通报,本周早些时候,执法人员截获了一个寄给特朗普总统的包裹,该包裹内包含蓖麻毒蛋白。

关键字: 美国 白宫 特朗普
关闭