嵌入式 LAB 3:自行车码表

前期工作准备

Mac OS X + Windows 7虚拟机

安装STM32 ST-LINK Unity。用于烧录程序。

安装STM32 ST-LINK所需要的驱动

安装Keil UVision 5,这是IDE,可以生成Hex文件,也可以烧录到板子上。

安装USB-TTL所以需要的驱动。

安装PUTTY,Windows下查看串口。

器材准备

STM32F103板子一个

杜邦线、面包线若干

ST-LINK V2

USB-TTL

按钮两个、面包板两个

Hex文件生成

切换成MDK-ARM

一定要选择Reset and Run。Build选项: Create HEX File选项,如下图所示。其实不使用ST-LINK Unity,直接使用Keil也是能够烧录下板的,但是需要使用Patch Installer下载一个Algorithm,经常会出现各种bug,我和队友在这里都出现了很多问题,所以用ST-LINK烧录是一个不错的选择。

烧录程序示意

连接方式

打开选择将要烧录的文件,然后

1、Erase Chip 擦出所有数据

2、Program & Verify

串口通信

实验步骤

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

配置UART0

改动的代码

结果如图所示

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

连接面包板

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

去抖动,其中MASK为0xFF,说明采集的区间为0xFF。

void anti_jitter(int *bit, int state){
    *bit <<= 1;
    *bit&= MASK;
     *bit|=state;
}

处理思路如下:

当State == 1时表示接通。

当State == 2时表示断开。

anti_jitter(&Pin_11_Bitcount,state_11);
anti_jitter(&Pin_12_Bitcount,state_12);
//如果位不全为0,而且现在的状态为0,那么转化为断开。
if(Pin_11_Bitcount != 0 && Pin_11_State == 0)
{
        Pin_11_State = 1;
        Change_Flag = 1;
}
if(Pin_12_Bitcount !=0 && Pin_12_State == 0)
{
        Pin_12_State = 1;
        Change_Flag = 1;
}
if(Pin_11_Bitcount == 0 && Pin_11_State == 1)
{
        Pin_11_State = 0;
        Change_Flag = 1;
}
if(Pin_12_Bitcount == 0 && Pin_12_State == 1)
{
        Pin_12_State = 0;
        Change_Flag = 1;
}
//如果状态发生改变,我们就观察一下PIN11和PIN12哪个是正常的。
if(Change_Flag == 1)
{
    Change_Flag = 0;
    count = sprintf(str,"Pin 11:%d\r\n",Pin_11_State);
    HAL_UART_Transmit(&UartHandle, (uint8_t*)str, count, 500);
    count = sprintf(str,"Pin 12:%d\r\n",Pin_12_State);
    HAL_UART_Transmit(&UartHandle, (uint8_t*)str, count, 500);
}

没有用Press。而是分别对两个按钮进行去抖动。观察是否有异常。

4、编写Cube程序,配置PA12下降沿触发中断,程序中设置两个全局变量,一个为计数器,一个为标识。当中断触发时,计数器加1,并设置标识。在主循环中判断标识,如果标识置位则清除标识并通过串口输出计数值

配置下降沿

配置中断

//定义两个全局变量

int T_Flag = 0;
int T_Count = 0;

//配置见上图

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == GPIO_PIN_12) {
        T_FLAG = 1 ;
    } else {
        UNUSED(GPIO_Pin);
    }
}

int main(void){
......
    while (1) {
        …
        int count;
        if (T_Flag==1) {
           T_Flag = 0;
           T_Count++;
           count = sprintf(str,"Pin 12:%d\r\n",Pin_12_State);
        HAL_UART_Transmit(&UartHandle, (uint8_t*)str, count, 500);
        }
    }
}

这一步的结果跟第三部没什么两样,所以图就不截了。

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

//定义两个全局变量

int T_Flag = 0;
int T_Count = 0;

void TIM_Init()
{
    T_Handler.Instance = TIM3;
   //时钟每1ms会被调用1次
    T_Handler.Init.Prescaler = 8000;
    T_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;
   //每个两百秒进行一次调用
    T_Handler.Init.Period = 199;
    HAL_TIM_Base_Init(&T_Handler);
    HAL_TIM_Base_Start_IT(&T_Handler);
}
//在中断触发时
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    T_Flag = 1;
}
int main(void){
......
    total = 0; bitcount = MAX_BITCOUNT;
    while (1) {
        …
        int count;
        if (T_Flag==1);
           T_Flag = 0;
           T_Count++;
           count!=!sprintf(str,"Time!clicks:!%d\r\n",T_Count);
           HAL_UART_Transmit(&UartHandle,(uint8_t!*)str,count,500)
        }
    }
}

效果图如下所示

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

思路:PA11和PA12都采用时间中断,下降沿触发。PA11能够切换模式,PA12触发的时候则能够记录车子走了多少圈。而时钟中断能够帮助我们统计时间。所以我们在主循环只需要每隔相应的时间输出特定模式下距离的值和速度的值。上面两个子问题的全局变量。一个用于记录是否到达一个时钟周期。另一个用于记录总的距离之和。

测试距离

测试速度

/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  *
  * COPYRIGHT(c) 2016 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

#define MASK 0xFF
#define DELAYTIME 5
#define SPDMODE 1
#define DISMODE 0
#define CHANGEMODE(M) (M = 1-M)
#define Tire_Perimeter 3

char str[30];
int Pin_12_Count = 0,Pin_12_Flag = 0;
TIM_HandleTypeDef T_Handler;
int mode=0;
float Distance = 0;

int T_Flag = 0;
int T_Count = 0;

int Change_Mode_Flag = 0;

void UART0_Init(UART_HandleTypeDef* UartHandle){
    UartHandle->Instance = USART1;
    UartHandle->Init.BaudRate = 9600;
    UartHandle->Init.WordLength = UART_WORDLENGTH_8B;
    UartHandle->Init.StopBits = UART_STOPBITS_1;
    UartHandle->Init.Parity = UART_PARITY_NONE;
    UartHandle->Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UartHandle->Init.Mode = UART_MODE_TX_RX;

        T_Count = 0;
        Distance = 0;
        mode = 0;

    HAL_UART_Init(UartHandle);
}

void TIM3_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&T_Handler);
}

void TIM_Init()
{
    T_Handler.Instance = TIM3;
   //输出慢一点
    T_Handler.Init.Prescaler = 8000*10;
    T_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;
    T_Handler.Init.Period = 199;
    HAL_TIM_Base_Init(&T_Handler);
    HAL_TIM_Base_Start_IT(&T_Handler);
}
//时间中断回调
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    T_Flag = 1;
    T_Count++;
}
//PIN12和PIN11的回调
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == GPIO_PIN_12) {
        Distance+=Tire_Perimeter;
    } else if(GPIO_Pin == GPIO_PIN_11)
    {
        Change_Mode_Flag = 1;
    } else {
        UNUSED(GPIO_Pin);
    }
}

/* USER CODE END 0 */

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();

  /* USER CODE BEGIN 2 */
        char str[30];
        int Pin_11_Bitcount = 0,Pin_12_Bitcount=0;
        int Pin_11_State=0,Pin_12_State=0;
        int Change_Flag=1;
    UART_HandleTypeDef UartHandle;
    UART0_Init(&UartHandle);
        TIM_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    HAL_UART_Transmit(&UartHandle, (uint8_t*)"Hello, World!\r\n", 16, 500);

  while (1)
  {
        int count;
  /* USER CODE END WHILE */
      //如果改变了模式,输出改变
        if(Change_Mode_Flag == 1)
        {
            Change_Mode_Flag = 0;
            CHANGEMODE(mode);
            if(mode == SPDMODE)
                count = sprintf(str,"Changed Into Speed Mode\r\n");
            else count = sprintf(str,"Changed into Distance Mode\r\n");
            HAL_UART_Transmit(&UartHandle,(uint8_t *)str,count,500);
        }
      //中断触发的时候
        if(T_Flag == 1)
        {
            T_Flag = 0;
            if(mode == SPDMODE) //根据不同的模式决定输出那个值
                count = sprintf(str,"Speed : %f\r\n",Distance/T_Count);
            else count = sprintf(str,"Distance : %f\r\n",Distance);
            HAL_UART_Transmit(&UartHandle,(uint8_t *)str,count,500);
        }
    }
    /* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* USART1 init function */
void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  HAL_HalfDuplex_Init(&huart1);

}

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pins : PA11 PA12 */
  GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif

/**
  * @}
  */ 

/**
  * @}
*/ 

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
时间: 2024-10-07 06:07:56

嵌入式 LAB 3:自行车码表的相关文章

嵌入式开发之 STM32自行车码表(图文)

笔者将从以下几个方面逐步深入地讲解STM32F103C8开发板的使用,并在Windows下编写一个简单的自行车码表程序: 元器件 环境搭建 电路连接 一个简单的LED闪烁程序 自行车码表 准备工作之 元器件 准备工作之 电路连接 准备工作之 环境搭建 CubeMX配置 KeilST-LINK下载程序调试程序 下载并注册安装Keil Keil安装程序及注册机 用keil打开CubeMX生成的工程文件 build keilST-LINK下载和调试以blink为例 出错误了 解决方法一 解决方法二 连

嵌入式LAB 1:启动

嵌入式系统Lab 1 启动 1. 画出你所实际实施的连接示意图 2.给出实际拍摄的板卡连接照片 3.给出所用的器材的列表 pcduino(含电源).USB串口线.网线.SD卡.无线网卡 显示屏.鼠标.键盘.支持L2TP路由器.MacBook Air 4.给出得到的pcDuino启动时的输出文字,并逐行解释 U-Boot 2009.08 (Dec 25 2014 - 21:37:33) # U-Boot: Universal Boot Loader, 负责嵌入式 Linux 系统的引导 CPU:

自行车码表

一.      实验目的和要求 1.    理解MCU上电启动过程: 2.    掌握使用Cube库来编写STM32裸机程序的方法: 3.    掌握使用Cube库来编写GPTO和UART程序的方法: 4.    掌握使用Cube库来编写中断响应程序的方法: 5.    理解前后台程序模式 6.    掌握在STM32F103上编写裸机程序并下载运行的方法. 二.      实验器材 1.    STM32F103核心板一块: 2.    MicroUSB线一根: 3.    STLink板或U

Bluemix公有云入华,IBM加入云大战,祭出三大杀器

(上图为IBM大中华区董事长陈黎明揭开了Bluemix公有云落地中国的大幕) 中国和印度正在成为全球炙手可热的云计算厂商争夺之地.根据451 Research在今年9月发布的调研数据,在两地有近200家云服务商,向本地客户提供IaaS.PaaS和SaaS服务.451 Research预测中国到2020年将创造159亿美元的云计算市场,而Gartner预测到2020年全球云计算市场营收为1435.3亿美元,也就是说届时中国将占全球云计算市场11%的份额. 2016年10月19日,IBM宣布正式与中

IBM的大数据云江湖,谁是新盟主?

大家都知道,在传统IT时代,数据库三巨头有IBM.Oracle和微软.在三巨头中,IBM可以说是绝对的数据库巨头,1968年就研发出了世界上第一个层次型数据库管理系统IMS,1970年IBM专家首次提出了数据关系模型的概念,1974年又提出了一种新型的数据查询语言也就是后来SQL的前身,1983年IBM发布了著名的DB2数据库,2001年以10亿美金收购了Informix. 然而到了云计算和大数据时代,一时风云变化.Hadoop和Spark等开源大数据存储与处理技术的崛起,导致了全球数据库市场格

智能可穿戴平台,你更看好谁?

随着可穿戴设备大潮来袭,众巨头纷纷布局可穿戴.6月,苹果发布了Healthkit平台,谷歌则发布了AndroidWare平台,日前,腾讯(微信)的智能硬件计划曝光.前两者从系统层面出发,都希望自己成为可穿戴行业的规则制定者,腾讯则依托微信这个大杀器,为硬件公司提供了一个新的选择. 苹果Healthkit HealthKit是苹果在iOS 8中新推出的健康信息管理系统,它可以整合iPhone或iPad上其它健康应用收集的数据,如血压和体重等.它能利用多种指标(如睡眠.运动,等等)追踪.记录和分析用

最全电商分类信息(03)

ID 上级ID 分类名称 分类等级 是否最终分类 2001 9708 其他运动包 2 1 2002 9708 运动钱包/卡包/钥匙包 2 1 2003 9708 运动手提包 2 1 2004 9708 运动双肩包 2 1 2005 9708 运动桶包 2 1 2006 9708 运动腰包 2 1 2007 9839 其他球类运动 2 1 2008 9886 麦克风 2 1 2009 9634 网线 1 1 2010 9842 数码相框 2 1 2011 10555 眼部卸妆 3 1 2012 9

RFID 电动二轮自行车的防盗系统—读头

RFID 电动二轮自行车的防盗系统-读头 在RFID电动自行车防盗系统中,2.4G的读头占有重要环节:关系到读标签跟将ID号传输到后台,在这里介绍一款2.4G RFID系统中无线链路的RFID收发芯片-SI24R1芯片. 现在介绍一下这款芯片的基本知识: Si24R1是一颗工作在2.4GHz ISM频段,专为低功耗无线场合设计,集成嵌入式ARQ基带协议引擎的无线收发器芯片.工作频率范围为2400MHz-2525MHz,共有126个1MHz带宽的信道. Si24R1采用GFSK/FSK数字调制与解

嵌入式Linux会议LinuxCon欧洲的时间表公布

From: http://linuxgizmos.com/embedded-linux-conference-and-linuxcon-europe-schedules-posted/ Linux基金会公布了LinuxCon + CloudOpen +嵌入式Linux大会欧洲的时间表,它们将在10月13-15日于德国的杜塞尔多夫举行.除了Linux基金会在七月初发布的LinuxCon + CloudOpen + ELC(嵌入式Linux大会)欧洲的主题演讲的初步名单外,Linux的倡导组织追加了