0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在STM32中要实现数据通讯

嵌入式应用开发 来源:嵌入式应用开发 作者:嵌入式应用开发 2022-03-02 08:56 次阅读

stm32中要实现数据通讯,首先要设置相关的寄存器,这里不做相关的介绍,直接说代码相关的能内容及相关函数对应的用法。

直接上代码。

1.串口通讯代码

usart.h

#ifndef __USART_H
#define __USART_H
#include "stdio.h"	
#include "sys.h" 

#define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART3_RX 			1		//使能(1)/禁止(0)串口1接收
	  	
extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART_RX_STA;         		//接收状态标记	
//如果想串口中断接收,请不要注释以下宏定义
void uart_init(u32 bound);
#endif

对应的usart.c代码

#include "sys.h"
#include "usart.h"	  


//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART3->SR&0X40)==0);//循环发送,直到发送完毕   
    USART3->DR = (u8) ch;      
	return ch;
}
#endif 

/*使用microLib的方法*/
 /* 
int fputc(int ch, FILE *f)
{
	USART_SendData(USART1, (uint8_t) ch);

	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}	
   
    return ch;
}
int GetKey (void)  { 

    while (!(USART1->SR & USART_FLAG_RXNE));

    return ((int)(USART1->DR & 0x1FF));
}
*/
 
#if EN_USART3_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  
  
void uart_init(u32 bound)
{
	//GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//使能USART1,GPIOA时钟
	
	//USART3_TX   GPIOB.10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB.10
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.10

	//USART3_RX	  GPIOB.11初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.11  

	//Usart3 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

	//USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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); //初始化串口3
  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART3, ENABLE);                    //使能串口3 

}

void USART3_IRQHandler(void)                	//串口3中断服务程序
{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res = USART_ReceiveData(USART3);	//读取接收到的数据
		printf("get data %c \r\n",Res);
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntExit();  											 
#endif
} 
#endif	

通过上述的函数,只需要在main函数设置相关的打印函数即可打印相关的内容,这里不做相关的陈述,后面主函数会进行相关的设置。

2.进行相关的adc函数配置

adc.h函数代码如下:

#ifndef __ADC_H
#define __ADC_H	
#include "sys.h"

void Adc_Init(void);
u16  Get_Adc(u8 ch); 
u16 Get_Adc_Average(u8 ch,u8 times); 
 
#endif

对应的adc.c函数代码:

 #include "adc.h"
 #include "delay.h"
//////////////////////////////////////////////////////////////////////////////////	 
//adc配置函数
////////////////////////////////////////////////////////////////////////////////// 
		   
//初始化ADC
//我们默认将开启通道0~3																	   
void  Adc_Init(void)
{ 	
	ADC_InitTypeDef ADC_InitStructure; 
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1	, ENABLE );	  //使能ADC1通道时钟
 

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

	//PC0 作为interwetten与威廉的赔率体系
通道输入引脚                         
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
	GPIO_Init(GPIOC, &GPIO_InitStructure);	

	ADC_DeInit(ADC1);  //复位ADC1 

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//模数转换工作在单通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//模数转换工作在单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

  
	ADC_Cmd(ADC1, ENABLE);	//使能指定的ADC1
	
	ADC_ResetCalibration(ADC1);	//使能复位校准  
	 
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束
	
	ADC_StartCalibration(ADC1);	 //开启AD校准
 
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
 
//	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能

}				  
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{
  	//设置指定ADC的规则组通道,一个序列,采样时间
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC1,ADC通道,采样时间为239.5周期	  			    
  
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能	
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC1规则组的转换结果
}

u16 Get_Adc_Average(u8 ch,u8 times)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t;t++)>

3.主函数内容

#include "delay.h"

#include "common.h"
#include "usart.h"	 
#include "can.h" 
#include "string.h" 
#define adcx adc;

 int main(void)
 {	 
	 int real_100_vol;
	u8 Res,res,data;
	u16 adcx;
	u8 i=0,t=0;
	u8 cnt=11;

	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
	Adc_Init();	        //adc初始化
   
	CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,8,CAN_Mode_LoopBack);//CAN初始化环回模式,波特率500Kbps ,设置8为500k,设置4为250k   
	printf("APP start OK!\r\n");
  
 	while(1)
	{
	
	char canbuf_8;
  int a = 165;
		adc=Get_Adc_Average(ADC_Channel_10,50);
		vol_led=(float)adc*(3.3/4096);
//		adcx=vol_led;
//		vol_led-=adcx;
//		vol_led*=1000;
		printf("AD值:%d\r\n 电压值:%f V",adc,vol_led);  //打印ad值和电压值
如何在STM32中要实现数据通讯



H文件与C文件进行配置。

即可通过串口读取到相关的数据AD值和电压值。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5336

    浏览量

    120244
  • 数据
    +关注

    关注

    8

    文章

    7006

    浏览量

    88947
  • 串口
    +关注

    关注

    14

    文章

    1551

    浏览量

    76438
收藏 人收藏

    评论

    相关推荐

    维爱普 数据通讯设备稳定性:滤波器的核心作用

    在当今这个信息爆炸的时代,数据通讯设备已经成为我们日常生活不可或缺的一部分。无论是智能手机、电脑,还是网络通信基站、数据中心,这些设备都在不断地传输、处理着海量的数据。然而,在
    的头像 发表于 12-17 16:57 77次阅读

    安信可智能无线数据通讯Ra-09-DTU

    Ra-09-DTU 是由安信可科技开发的一款智能无线数据通讯DTU,采用Ra-09 LoRa 模组,利用 LoRa 无线威廉希尔官方网站 可用于超长距离扩频通信。其芯片 STM32WLE5CCU6 是通用
    的头像 发表于 12-05 14:32 143次阅读
    安信可智能无线<b class='flag-5'>数据通讯</b>Ra-09-DTU

    求助,关于ADS125H02数据通讯格式及CRC校验问题求解

    of the initial data. 第1条,将所有数据“左移扩展为40bit,最右边用1补齐”,与传统的crc计算方法不一致,传统的计算方法是在数据末尾补8个0。是手册笔误还是本就与正常的crc计算方法
    发表于 12-03 06:54

    EtherCAT转Modbus TCP总线协议转换网关

    远创智控YC-ECT-TCP型网关实现EtherCAT网络与Modbus TCP网络之间的数据通讯,即将Modbus TCP设备转换为EtherCAT设备。
    的头像 发表于 09-30 16:04 245次阅读
    EtherCAT转Modbus TCP总线协议转换网关

    EtherCAT转Modbus TCP协议网关(JM-ECT-TCP)

    JM-ECT-TCP网关实现EtherCAT网络与Modbus TCP网络之间的数据通讯,即将Modbus TCP设备转换为EtherCAT设备。
    的头像 发表于 09-07 17:05 338次阅读
    EtherCAT转Modbus TCP协议网关(JM-ECT-TCP)

    何在反激式拓扑实现软启动

    电子发烧友网站提供《如何在反激式拓扑实现软启动.pdf》资料免费下载
    发表于 09-04 11:09 0次下载
    如<b class='flag-5'>何在</b>反激式拓扑<b class='flag-5'>中</b><b class='flag-5'>实现</b>软启动

    HT1S-COP-MDN-S10 网关与台达PLC(CANOPEN)数据通讯配置说明

    本案例测试主要实现采集多个MODBUS RTU设备接入到台达CANOPEN接口的PLC进行数据通讯
    的头像 发表于 06-13 15:19 703次阅读
    HT1S-COP-MDN-S10 网关与台达PLC(CANOPEN)<b class='flag-5'>数据通讯</b>配置说明

    STM32F103 USB通讯出现数据丢失的原因?如何解决?

    用ST32F103的USB 做数据通讯,有大量的数据通过电脑发送到设备,少量数据回传到电脑,中断优先级设为2 ,还有几个定时器的也是中断,优先级比USB通讯的高,发现在大量连续发送
    发表于 04-29 07:28

    浅谈光伏电站数据通讯管理机的设计与应用

    浅谈光伏电站数据通讯管理机的设计与应用 张颖姣 江苏安科瑞电器制造有限公司江苏江阴214405 摘要 :设计了一种分布式光伏电站数据通讯管理机,包括硬件系统和软件系统.硬件系统基于ARM嵌入式处理器
    的头像 发表于 03-14 10:23 565次阅读
    浅谈光伏电站<b class='flag-5'>数据通讯</b>管理机的设计与应用

    串口通讯时的数据帧格式和通讯协议有什么区别?

    串口通讯时的数据帧格式和通讯协议是两个不同的概念,它们在串口通讯起着不同的作用,但都是为了实现
    的头像 发表于 01-30 09:21 1999次阅读

    IXXAT CAN-IB系列高稳定性通讯板卡

    CAN板卡经常应用于构建现场总线测试实验室、工业控制、智能楼宇、汽车电子等领域中,进行数据采集、数据通讯数据处理。
    的头像 发表于 01-19 15:04 1045次阅读
    IXXAT CAN-IB系列高稳定性<b class='flag-5'>通讯</b>板卡

    PLC之间数据通讯,PLC与智能仪表、设备之间WIFI无线通讯

    各种PLC之间双向通讯 不同品牌不同型号的PLC,实现多对多的N:N通讯;同时支持以太网、串口连接;无需编写程序,简单配置主从站点的起始地址、数据长度即可;各站点多线程方式独立运行,
    发表于 01-07 11:22

    光纤的优势和物理结构

    正如我们所知,光纤通讯在我们今天的社会有着非常广泛的应用。互联网的普及又依托在高性能的数据通讯上,而高速数据通讯,又依赖于高速的传输介质,就是我们今天所说的光纤。
    的头像 发表于 01-04 09:24 1029次阅读
    光纤的优势和物理结构

    虹科威廉希尔官方网站 | 保障数据传输稳定性:BabyLIN产品的CRC算法实现

    CRC校验(循环冗余校验)是数据通讯中最常采用的校验方式。CAN协议,总线通信节点也常采用CRC算法对各种总线传输的数据进行校验。
    的头像 发表于 01-02 17:23 536次阅读
    虹科威廉希尔官方网站
 | 保障<b class='flag-5'>数据</b>传输稳定性:BabyLIN产品的CRC算法<b class='flag-5'>实现</b>

    PLC通过智能网关,与OPCUA服务端通讯实现标签数据读写

    通过‘功能’-&gt;‘数据上报与平台对接’,选择‘专用协议数据通讯’,进入以下页面配置发送数据(OPCUA发送到PLC的数据)、接收数据
    发表于 01-02 16:41