历史上的今天
返回首页

历史上的今天

今天是:2025年04月22日(星期二)

正在发生

2018年04月22日 | 基于stm32CubeMX和keil5的stm32f103学习编程

2018-04-22 来源:eefocus

0. 准备

先用st-link连接stm32核心板与PC,用于烧录

St-link

Stm32

3.3V

3.3V

GND

GND

SWDIO

DIO

SWCLK

DCLK

再用USB串口板连接,用于查看串口输出

USB

Stm32

RX

TX(A9)

TX

RX(A10)

安装完成驱动并连接好以后,进入设备管理器可以看到它们都已被识别。

打开putty.exe,选择串口连接,用于查看之后的串口输出。



1. 编写Cube程序,配置UART0为9600,8n1,上电后向串口输出“Hello”,在PC上通过串口软件观察结果;

安装完成并打开CubeMX软件,选择New Project,选择STM32F103C8Tx并点击ok。



进入工程界面以后我们可以看到右边有芯片的引脚图,如下所示。我们点击PA11和PA12,选择GPIO_Input(后面按钮用)。然后在左边的配置中将UART1模式定为Half-Duplex。

在生成代码前,进入工程配置。填写工程名、保存路径等,同时选择IDE为MDK-ARM V5。



设置完成后点击生成代码。注意如果没安装库文件的话会提示下载,但通过软件的自动更新速度无比的慢,而且经常下一半会挂,所以可以在网络上下载后自助导入。

生成代码后弹出如下对话框,选择open。



进入keil5以后可以看到我们的工程文件目录如左栏所示。注意打开前会弹出Pack installer下载对应的编程工具,选择stm32f1xx系列即可。下载有点慢,可以自己下载或拷贝他人后导入,路径为 c:/keil v5/ARM/Pack


然后进入main.c对UART进行配置为9600,8n1,代码如下所示。


  1. void UART0_Init(UART_HandleTypeDef* UartHandle){  

  2.     UartHandle->Instance = USART1;  

  3.     UartHandle->Init.BaudRate = 9600;  

  4.     UartHandle->Init.WordLength = UART_WORDLENGTH_8B;  

  5.     UartHandle->Init.StopBits = UART_STOPBITS_1;  

  6.     UartHandle->Init.Parity = UART_PARITY_NONE;  

  7.     UartHandle->Init.HwFlowCtl = UART_HWCONTROL_NONE;  

  8.     UartHandle->Init.Mode = UART_MODE_TX_RX;  

  9.    

  10.     HAL_UART_Init(UartHandle);  

  11. }  


在main函数中填上下面两行代码­


  1.   UART_HandleTypeDef UartHandle;  

  2.   UART0_Init(&UartHandle);  



以及输出hello的代码


  1. HAL_UART_Transmit(&UartHandle, (uint8_t*)”hello\r\n”, 7, 500);  


完成代码后,­准备编译。选择flash-设置,进入Utilities标签,选择settings,配置如下:



然后F7编译完成后将程序烧录至核心板,按一下板子上的reset开关就可以在putty看到串口输出了。



2. 通过面包板在PA11和PA12各连接一个按钮开关到地;



3. 编写Cube程序,配置PA11和PA12为内部上拉到输入模式,在main()函数循环检测PA11按钮按下,并在按钮按下时 在串口输出“Pressed”;

可以在CubeMX中图形化地更改引脚设置,也可以直接在代码中修改:


  1. void MX_GPIO_Init(void)  

  2. {  

  3. ……  

  4.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;  

  5.   GPIO_InitStruct.Pull = GPIO_PULLUP;  

  6. ……  

  7. }  

在while(1)中添加代码,循环检测并输出


  1. ……  

  2.   if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11))  

  3.    HAL_UART_Transmit(&UartHandle, (uint8_t*)”Pressed\r\n”, 9, 500);  

  4.   else  

  5.    HAL_UART_Transmit(&UartHandle, (uint8_t*)”Not pressed\r\n”, 13, 500);  

  6. ……  


输出如图



4. 编写Cube程序,配置PA12下降沿触发中断,程序中设置两个全局变量,一个为计数器,一个为标识。当中断触发 时,计数器加1,并设置标识。

在主循环中判断标识,如果标识置位则清除标识并通过串口输出计数值;

在GPIO的init函数中为PIN12设置下降沿中断,并设置优先级。


  1. GPIO_InitStruct.Pin = GPIO_PIN_12;  

  2. GPIO_InitStruct.Mode = GPIO_MODE_INPUT;  

  3. GPIO_InitStruct.Pull = GPIO_PULLUP;  

  4. GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;  

  5. HAL_NVIC_SetPriority(EXTI15_10_IRQn,0,0);  

  6. HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);  

  7. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  


PA12引脚的下降沿触发将会触发中断,进入函数EXTI15_10_IRQHandler,此时在函数中调用HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12)表示查看PA12的值,如果符合条件,则触发HAL_GPIO_EXTI_Callback函数。代码如下


  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){  

  2.     if (GPIO_Pin == GPIO_PIN_12){  

  3.         PA12flag = 1;  

  4.         PA12cnt++;  

  5.     }else{  

  6.         UNUSED(GPIO_Pin);  

  7.     }  

  8. }  


在main函数的while循环中添加代码:


  1. if(PA12flag == 1){  

  2.   PA12flag = 0;  

  3.   size = sprint(str, ”Count: %d\r\n”,PA12cnt);  

  4.   HAL_UART_Transmit(&UartHandle, (uint8_t*)str, size, 500);  

  5. }  




5. 编写Cube程序,开启定时器为200ms中断一次,中断触发时设置标识,主循环根据这个标识来做串口输出(取消4 的串口输出);

使用TIM3定时器,如果不是CUBEMX生成代码的话记得添加头文件引用。

添加init函数:


  1. void TIM_Init(){  

  2.     TIM_Handle.Instance = TIM3;  

  3.        TIM_Handle.Init.Prescaler = 8000;  

  4.        TIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;  

  5.        TIM_Handle.Init.Period = 199;  

  6.        TIM_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;  

  7.         

  8.        HAL_TIM_Base_Init(&TIM_Handle);  

  9.          

  10.        sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; //设置时钟源为内部时钟  

  11.        HAL_TIM_ConfigClockSource(&TIM_Handle, &sClockSourceConfig);  

  12.        sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;//设置复位模式,发生触发输入事件时计数器和预分频器能重新初始化  

  13.        sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;  

  14.        HAL_TIMEx_MasterConfigSynchronization(&TIM_Handle, &sMasterConfig);  

  15.         

  16.        HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);//设置优先级  

  17.        HAL_NVIC_EnableIRQ(TIM3_IRQn);enable中断向量表处理    

  18. }  


和之前设置的中断一样需要覆写中断触发函数TIM3_IRQHandler,而后在其中对时钟进行判断后触发HAL_TIM_PeriodElapsedCallback。并在callback中实现操作。


  1. TIM_HandleTypeDef TIM_Handle;  

  2. TIM_ClockConfigTypeDef sClockSourceConfig;  

  3. TIM_MasterConfigTypeDef sMasterConfig;     

  4.                

  5. int TIMflag = 0, PA12flag = 0;  

  6. int TIMcnt = 0, PA12cnt = 0, totalcnt = 0;  

  7.    

  8. void TIM3_IRQHandler(void){  

  9.     HAL_TIM_IRQHandler(&TIM_Handle);  

  10. }  

  11.    

  12. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){     

  13.     TIMflag = 1;  

  14.               TIMcnt++;  

  15. }  

6. 编写完整的码表程序,PA12的按钮表示车轮转了一圈,通过计数器可以得到里程,通过定时器中断得到的时间可以计算出速度;PA11的按钮切换模式,模式一在串口输出里程,模式二在串口输出速度。

在main函数中实现码表程序:

  1. while (1)  

  2.   {  

  3.   /* USER CODE END WHILE */  

  4.   /* USER CODE BEGIN 3 */  

  5.               if(TIMflag == 1){  

  6.                             TIMflag = 0;  

  7.               if(TIMcnt == 5){每五个周期输出一次  

  8.                      speed = 2 * PA12cnt / 1;//五个周期为1秒,车轮周长2米  

  9.                      TIMcnt = 0;  

  10.    

  11.               if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11))  

  12.                      mode = 1 - mode;//PA11按钮负责模式切换  

  13.               switch(mode){  

  14.                      case 0:  

  15.                             size = sprintf(str, "Speed : %f \r\n",speed);//输出速度  

  16.                             HAL_UART_Transmit(&UartHandle, (uint8_t*)str, size, 500);  

  17.                             break;  

  18.                      case 1:  

  19.                             size = sprintf(str, "Mileage: %d \r\n", 2 * totalcnt);//输出里程  

  20.                             HAL_UART_Transmit(&UartHandle, (uint8_t*)str, size, 500);  

  21.                             break;  

  22.                      default:break;  

  23.                      }  

  24.                      PA12cnt = 0;  

  25.               } }  


推荐阅读

史海拾趣

Cypress Industries公司的发展小趣事

Cypress Semiconductor于1982年在美国加州的硅谷成立,这里是全球半导体行业的发源地之一。公司起初专注于高性能IC产品的研发和生产,为数据传输、远程通讯等领域提供解决方案。随着技术的不断发展和市场的扩大,Cypress逐渐将业务拓展至全球,并在多个国家和地区建立了生产基地和设计中心。

Chip Quik公司的发展小趣事

随着国内市场的稳定发展,Chip Quik公司开始将目光投向国际市场。公司通过分析不同国家和地区的电子维修市场需求,制定针对性的市场策略。通过参加国际电子展会、建立海外销售渠道等方式,公司逐渐在国际市场上取得了一席之地。

国盛科技(BOCHEN)公司的发展小趣事

国盛科技在技术创新方面取得了显著成果。截至目前,公司已累计取得8项发明专利、30项新型实用型专利,并成功转化了19项高新技术产品和知识产权成果。这些专利和成果的取得,不仅展示了国盛科技在电子元器件领域的研发实力,也为公司的持续发展提供了有力支撑。

Elcos AG公司的发展小趣事

随着全球对环保和可持续发展的重视,Elcos AG也开始注重自身的环保责任和可持续发展战略。公司采用环保材料和生产工艺,减少了对环境的污染和资源的浪费。同时,Elcos AG还积极参与社会公益事业和环保活动,通过捐款、赞助和志愿服务等方式回馈社会。这些举措不仅提升了公司的社会形象和品牌价值,也为公司的长期发展奠定了坚实的基础。

CUI Inc.公司的发展小趣事

自1989年成立以来,CUI Inc.一直站在电源设计的前沿。公司不断投资于研发,致力于开发出更高效、更环保的电源产品。通过引入先进的电源管理技术和创新的设计方法,CUI成功地帮助客户提高了应用的能效,减少了能源消耗。这种对电源技术的专注和创新,使CUI在竞争激烈的电子行业中脱颖而出,赢得了众多客户的信赖和好评。

Golledge Electronics公司的发展小趣事

CUI Inc.一直坚信,与客户的紧密合作是其成功的关键。因此,公司始终致力于与客户发展协作性伙伴关系。通过深入了解客户的需求和反馈,CUI不断优化其产品和服务,以满足客户的期望。这种以客户为中心的经营理念不仅赢得了客户的忠诚和支持,还为CUI带来了持续的业务增长和市场份额的扩大。

这些故事只是CUI Inc.在电子行业中发展起来的一部分可能情况。实际上,CUI的发展可能涉及更多的战略决策、市场变化和技术突破。如果需要更具体、详细的故事,建议查阅相关的行业报告、公司年报或新闻资讯。

问答坊 | AI 解惑

有用过转接卡的吗?pcmcia转串口 在超级终端中输入的字符混乱

使用的是华塑的pcmcia转串口卡,XP系统自带超级端连mini2440 波特率:115200 数据位:8 奇偶校验:无 停止位:1 数据流控制:无 在设置中的\"本地回显键入的字符\",没有勾选. 可以连上mini2440,之前刷的是\"缺省Linux系统\",在超级终端中能 ...…

查看全部问答>

在调AD的时候都要注意什么问题啊?

本帖最后由 paulhyde 于 2014-9-15 09:01 编辑 我是新手,最近调了个AD574,感觉时序都没问题,可出来的数就是不变。不知道AD这块还要注意点什么啊?  …

查看全部问答>

向大家请教一下!

#define TRANDATA_TOGSM_TIMES 0350h #define UP_3mA 0352h #define UP_10mA 035Eh ;这是一个6个字长的数组,放置峰值大于10mA的数量 ;该数组占据的地址空间为35E/360/362/364/366/368 #define Rain_Counter_Day 0400 ...…

查看全部问答>

生产厂家规范的-- LED驱动电源测试报告范例

replyreload += \',\' + 1365593;这份报告是基于一个8W LED驱动电源临时做的一个基本范例,是考虑有公司商业机密的问题,略作修改: 1.不对版权负责,只供参考. 2.不对内容负责,不做解释.每家公司各不相同,难于解释不同.敬请谅解. Timson,如果您要 ...…

查看全部问答>

[转贴]实施DDR 2 / mddr布局的tms320dm35x dmsoc 大家可以参考一下!很有用!!

摘要:         该tms320dm35x数字媒体系统芯片(dmsoc)装置。该方法来指定接口时序的DDR 2 / mddr接口是完全不同的,比以前的设备。         前一种方法指定计时装置在数据表规格 ...…

查看全部问答>

关于ISE中的约束语句

今天看到一个例子,该例子中用了下面这些语句 (* KEEP = \"TRUE\" *),貌似是用来防止wire型被综合掉 ?? (* INIT = \"0\" *),初始化一个寄存器的值为0 ?? (* ASYNC_REG = \"TRUE\" *)    ?? 请问这些语句是什么语句?有什么用 ...…

查看全部问答>

ad测量通过串口发出的程序,只能发出FF

我用AD采样,然后想通过串口发出,结果只能得到FF。大家帮我看看那里出现了问题,谢谢 #include  \"msp430g2553.h\" #define uchar unsigned char long temp; void uart_init(void) {         BCSCTL1 = CAL ...…

查看全部问答>

鍵盤A鍵和B鍵交替輸入效果

將鍵盤上A鍵和B鍵的4個接觸點伸延出來(因為是接觸按鍵,所以每個按鍵都有2個接觸點), 我想透過一組電子零件來接駁伸延出的4個接觸點, 啟動該製成品後在顯示螢幕上出現ABABABAB...連續按鍵的效果。 當然如果使用軟件來達成簡直是易如反掌,但我 ...…

查看全部问答>

【TIVA C Launchpad 学习笔记三】利用PWM模块产生两路方波

/******************************************* 开发坏境:CCSv5 程序功能:利用PWM模块产生两路方波 程序说明:使用PWM模块0,PWM发生器0,输出为PWM0和PWM1管脚,分别为PB6,PB7 编程者:Linchpin ******************************************* ...…

查看全部问答>