串口通信——stm32F407实现串口发送坐标,输出x坐标和y坐标

这篇具有很好参考价值的文章主要介绍了串口通信——stm32F407实现串口发送坐标,输出x坐标和y坐标。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 实验目的

通过串口助手发送一个(a,b),需要输出x = a,y = b;

2. 实验准备和流程

初始化串口;
编写接收数据中断函数;
编写转换函数;
编写main函数。

2.1 初始化串口

//配置中断函数,这个函数下面有调用
 void EXTI_NVIC_Config(void){
	//NVIC初始化结构体
	NVIC_InitTypeDef  NVIC_InitStruct;
	//设置中断优先级的分组
	//就是设置主抢占优先级和子抢占优先级各是几,这里是分组为1,代表主优先级可以是0和1(就是1个位来设置主优先级),子优先级是0-7,是2的3次方
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	//配置USART为中断源
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
	//配置抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	//配置子优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	//使能中断
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}
//串口初始化函数
void USART_Config(void){
	//1.初始化GPIO(PA9(接串口1的TX引脚),这里是PA10(接串口1的RX引脚))
	//初始化结构体 GPIO_InitStruct
	//里面是GPIO的速度,上下拉,输出类型等
	 GPIO_InitTypeDef   GPIO_InitStruct;
	//USART结构体
	 USART_InitTypeDef   USART_InitStruct;
	//打开GPIOA时钟(一般开时钟要放到前面的位置,然后再是设置上拉,输出这些)
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);  //使能时钟必须放到前面,不然后面的操作不会使灯点亮
	//打开USART1时钟
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
	//复位串口1
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,  GPIO_AF_USART1); //PA9 复用为 USART1
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //PA10 复用为 USART1
	//驱动是哪个引脚  PA9/PA10
	GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_9|GPIO_Pin_10;
	//模式是复用功能
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
	//输出的速度
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	//推挽复用输出
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	//上拉
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
	//变量获取它的指针,取地址就行(&)
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	//2.初始化串口
	//使能串口时钟 (放在最上面了)
	//配置波特率
	USART_InitStruct.USART_BaudRate = 115200;  //设置波特率115200
	//配置针数据字长
	USART_InitStruct.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
	//配置停止位
	USART_InitStruct.USART_StopBits = USART_StopBits_1;     //设置为一个停止位
	//配置校验位
	USART_InitStruct.USART_Parity = USART_Parity_No;     //无奇偶校验位
	//配置硬件流控制
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不使用硬件流控制
	//配置工作模式
	USART_InitStruct.USART_Mode =  USART_Mode_Rx|USART_Mode_Tx;  //收发模式
	//完成串口的初始化配置
	USART_Init(USART1,&USART_InitStruct);
	//串口中断优先级配置(初始化)
	EXTI_NVIC_Config();
	//使能串口接收中断(中断配置函数)  这是使能哪种中断,比如在接收到数据的时候(RXNE 读数据寄存器非空),我们要产生中断
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);  //生成串口中断   接收到数据就产生了中断
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);	// 开启空闲中断
	//使能串口(串口使能函数)
	USART_Cmd(USART1,ENABLE);
}

2.2 编写接收数据中断函数

typedef struct {
  char USART1_RX_BUF[320];  //声明一个缓冲数组

  uint16_t USART1_RX_BUF_length;  //记录缓存数组的长度

  uint16_t comma_Index;  //记录逗号的索引

  uint16_t Data_flag;  //接收完数据的标志

  int16_t cnt;  //数组的索引值

  int16_t x_value;  // x坐标值, 这里定义要有符号

  int16_t y_value;  // y坐标值, 这里定义要有符号

} UsartTypeDef;  //串口结构体
//接收数据中断函数
void USART1_IRQHandler(void) {
  //当 RDR 移位寄存器的内容已传输到 USART_DR 寄存器时,该位由硬件置 1。代表数据接收完成
  if (USART_GetITStatus(USART1, USART_IT_RXNE)) {  //接收到数据了
    UsartStructure.USART1_RX_BUF[UsartStructure.cnt] = USART_ReceiveData(USART1);
    if (UsartStructure.USART1_RX_BUF[UsartStructure.cnt] == 0x29) {  //判断是否接收到右括号,也就是右括号代表着接收结束,这里也可以写 == ")"
      UsartStructure.USART1_RX_BUF_length = UsartStructure.cnt;      //记录串口缓存数组长度
      UsartStructure.cnt = 0;  //缓存数组索引置为0
      UsartStructure.Data_flag = 1;
    } else {
      UsartStructure.cnt++;
    }
    if (UsartStructure.cnt >= 320 || !(UsartStructure.USART1_RX_BUF[0] == 0X28)) {  //接收数据异常,初始化数组,第一个接收到左半边括号
      UsartStructure.cnt = 0;
    }
  }
}

2.3 编写转换函数

 char ASCII_To_Value(char asc) {                       //ASCII转换成数字的函数
  char value;
  switch (asc){
    case 0x30:											//0的ASC码时0x30,十进制48
      value = 0;
      break;          
    case 0x31:
      value = 1;
      break;
    case 0x32:
      value = 2;
      break;
    case 0x33:
      value = 3;
      break;
    case 0x34:
      value = 4;
      break;
    case 0x35:
      value = 5;
      break;
    case 0x36:
      value = 6;
      break;
    case 0x37:
      value = 7;
      break;
    case 0x38:
      value = 8;
      break;
    case 0x39:
      value = 9;
      break;
  }
  return value;
}
void receive_coordinate(char *array) {
  uint16_t i = 0;
  int16_t x_value = 0;
  int16_t y_value = 0;

  for (i = 0; i < UsartStructure.USART1_RX_BUF_length; i++) {
    if (array[i] == 0X2C) {          //检测英文逗号
      UsartStructure.comma_Index = i;
    }
  }
  if (array[1] == 0X2D) {           //判断是负号
    for (i = 2; i < UsartStructure.comma_Index; i++) {
      x_value += ASCII_To_Value(array[i]) * pow(10, UsartStructure.comma_Index - i - 1);  //转换成数字
    }
    UsartStructure.x_value = -x_value;

  } else {  //不为负号
    for (i = 1; i < UsartStructure.comma_Index; i++) {
      x_value += ASCII_To_Value(array[i]) * pow(10, UsartStructure.comma_Index - i - 1);  //转换成数字			
    }
    UsartStructure.x_value = x_value;
  }

  if (array[UsartStructure.comma_Index + 1] == 0X2D) {  //判断逗号后一个的是否为负数
    for (i = UsartStructure.comma_Index + 2; i < UsartStructure.USART1_RX_BUF_length; i++) {
      y_value += ASCII_To_Value(array[i]) * pow(10, UsartStructure.USART1_RX_BUF_length - i - 1);  //转换成数字
    }
    UsartStructure.y_value = -y_value;
  } else {
    for (i = UsartStructure.comma_Index + 1; i < UsartStructure.USART1_RX_BUF_length; i++) {
      y_value += ASCII_To_Value(array[i]) * pow(10, UsartStructure.USART1_RX_BUF_length - i - 1);  //转换成数字
    }
    UsartStructure.y_value = y_value;
  }
}

2.4 main.c函数

int main(void) {
  delay_init(168);  //初始化延时函数
  USART_Config();

  while (1) {

    if (UsartStructure.Data_flag == 1) {
      receive_coordinate(UsartStructure.USART1_RX_BUF);  //传入数组

      UsartStructure.Data_flag = 0;  //数据接收标志位置为0

      printf("x_value = %d\r\n", UsartStructure.x_value);

      printf("y_value = %d\r\n", UsartStructure.y_value);
    }
  }
}

3. 实验结果

如下图所示:
串口通信——stm32F407实现串口发送坐标,输出x坐标和y坐标,单片机,stm32,单片机,嵌入式硬件
串口通信——stm32F407实现串口发送坐标,输出x坐标和y坐标,单片机,stm32,单片机,嵌入式硬件
串口通信——stm32F407实现串口发送坐标,输出x坐标和y坐标,单片机,stm32,单片机,嵌入式硬件

4. 总结

在数据的类型上,x和y的坐标值类型是 int16_t ,就是有正负号,写程序是开始写成uint16_t,导致输出负数错误。文章来源地址https://www.toymoban.com/news/detail-626261.html

到了这里,关于串口通信——stm32F407实现串口发送坐标,输出x坐标和y坐标的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32F407 CAN模块发送接收数据异常

    现象: 1、CAN模块初始化成CAN_MODE_LOOPBACK模式 CAN模块通过HAL_CAN_AddTxMessage发送数据时,TX管脚能够发出数据,示波器也可以测量到数据波形,CAN使用中断接收HAL_CAN_ActivateNotification或者查询接收HAL_CAN_GetRxMessage都可以接收到正确的数据(和发送的数据一致),但是CAN接口却没有波

    2024年02月12日
    浏览(41)
  • 关于STM32F407ZGT6的USB损坏后使用ST-Link和USART1实现串口功能

    开发板:STM32F407ZGT6; 目标:想使用软件“串口调试助手” 情况:开发板上的USB_UART口所在器件损坏或者直接没有;   解决办法:查看该开发板的原理图,可得:串口1的RX接TXD,串口1的TX接RXD,那么按如下步骤操作: 1、现在使用USB转TTL模块,将串口1的RX接USB转TTL模块的TXD,

    2024年02月08日
    浏览(47)
  • 关于STM32F407ZGT6的USB_UART端口损坏后使用ST-Link和USART1实现串口功能

    开发板:STM32F407ZGT6; 目标:想使用软件“串口调试助手” 情况:开发板上的USB_UART口所在器件损坏或者直接没有;   解决办法:查看该开发板的原理图,可得:串口1的RX接TXD,串口1的TX接RXD,那么按如下步骤操作: 1、现在使用USB转TTL模块,将串口1的RX接USB转TTL模块的TXD,

    2024年02月07日
    浏览(48)
  • stm32F407学习DAY.14 在DMA模式下进行USART串口数据收发(正点原子例程为例)

    目录 一、DMA配置 1、DMA1和DMA2的请求映射 2、DMA挂载总线 3、DMA相关库函数 ​4、DMA配置过程(以串口1为例) 1)进行时钟使能 2)等待DMA可配置 3)初始化DMA(串口1的TX为DMA2 数据流7 通道4,RX为DMA2 数据流5 通道4) a.DMA外设地址par: b.DMA存储器0地址mar: c.数据传输量ndtr: 4)

    2024年02月04日
    浏览(46)
  • 【DRV8323】电机驱动芯片寄存器配置指南,通过STM32F407的SPI通信配置

    笔者计划使用一块使用到STM32F407控制芯片与DRV8323s驱动芯片的板子,驱动BLDC。了解到需要使用SPI通信来配置DRV8323s驱动芯片,配置过程中涉及DRV8323数据手册中提及的几个寄存器,故写此文做个记录。 另外,DRV8323芯片和DRV8302、DRV8303、DRV8353都有极大的相似之处,可以相互参考

    2024年02月02日
    浏览(59)
  • 【STM32】BLDC驱动&控制开发笔记 | 07_SPI通信测试 - STM32F407用SPI配置DRV8323驱动芯片

    最近在埋头搞STM32 + 无刷直流电机控制,想实现用自己的STM32F407VGT6芯片板子,外加一块驱动板(目前选用到TI的DRV8302或者DRV8323驱动芯片),搞定电机驱动,最后实现比较好的控制效果。如果不是同一块芯片的同学也不用急着走,大体上都是可借鉴哒~ 本文主要实现使用SPI通信

    2024年02月08日
    浏览(50)
  • STM32F407实现1588v2(ptpd)

    硬件: STM32F407ZGT6开发板 软件: VSCode arm-none-eabi-gcc openOCD st-link 在github搜到一个在NUCLEO-F429ZI开发板上移植ptpd的example,因为和F407差别很小,所以就打算用这个demo移植到手头的开发板上。因为目前只需要slave,所以只调试了slave。据介绍,master好像原作者没有充分测试过。 源项

    2024年02月08日
    浏览(38)
  • 基于STM32F407实现超声波测距(SR04)

    今天要实现的功能是超声波测距,这一功能在很多的地方都能用到,比如:在智能小车上可以添加超声波避障功能。今天需要用到SR04超声波模块,在使用这一模块的时候我很会接触到时序图。 模块如图所示: 模块有四个引脚 VCC 供 5V电源, GND 为地线, TRIG 触 发 控 制 信 号

    2024年02月11日
    浏览(54)
  • 从STM32F407到AT32F407(一)

    雅特力公司的MCU有着性能超群,价格优越的巨大优势,缺点是相关资料少一些,我们可以充分利用ST的现有资源来开发它。 我用雅特力的STM32F437开发板,使用原子 stm32f407的开发板自带程序,测试串口程序,原设定串口波特率为115200,但是输出乱码,波特率改成230400,串口输

    2024年02月02日
    浏览(57)
  • 利用是stm32cubemx实现双极性spwm调制 基于stm32f407vet6

    【双极性SPWM调制讲解以及基于stm32的代码生成-哔哩哔哩】 https://b23.tv/ytFxdkL 双极性spwm调制虽然没有单极性好用,但比单极性要简单易懂一些,以下教程是如何利用stm32实现双极性spwm调制.   •T1,T2不能同时导通,T3,T4也不能同时导通,否则短路烧管子。 •解决方法:T1与T2用高

    2024年02月15日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包