在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 作为模拟通道输入引脚
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值和电压值

H文件与C文件进行配置。
即可通过串口读取到相关的数据AD值和电压值。
审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
寄存器
+关注
关注
31文章
5588浏览量
129033 -
数据
+关注
关注
8文章
7314浏览量
93938 -
串口
+关注
关注
15文章
1607浏览量
81909
发布评论请先 登录
相关推荐
热点推荐
ProfiNet转Ethernet/IP 配置案例:实现三菱FR-E800变频器与S7-1500通讯
Profinet转EtherNet/IP 专业通讯网关应运而生,成为实现二者高效数据通讯的核心枢纽。 在某大型自动化生产车间,为优化电机驱动控制流程,提升生产效率,需要实现 Prof
E+H 91W电磁流量计hart转485通讯应用
1.E+H 91W电磁流量计2.E+H hart转485裸板
91W电磁流量计内嵌式hart转485裸板安装
91W电磁流量计内嵌式hart转485数据通讯
发表于 11-12 15:20
如何在下载程序时保护flash中的用户数据不被覆盖?
使用stm32cubeide或stm32cubeprogrammer烧写程序,stlink下载器,芯片stm32h743,芯片内部flash的0x08100000地址中写有用户
发表于 08-14 06:38
阀岛如何通过Modbus转Profibus网关实现高效通讯!
在现代工业自动化领域,不同设备和系统间的数据通讯是确保生产效率与安全的关键因素之一。为了实现不同通信协议的设备无缝对接,提高整个自动化系统的兼容性和灵活性,开疆智能Modbus转Profibus网关
Profibus转Modbus网关:大屏数据通讯的协议转换方案
广泛使用的通讯协议,各自在不同工业自动化系统中发挥着重要作用。当面对特定应用需求如LED大屏显示时,实现这两种协议之间的无缝连接和数据通讯显得尤为重要。无锡耐特森Profibus转Modbus网关
ProfiNet转Ethernet/IP协议网关实现三菱FR-E800系列变频器与西门子S7-1500系列PLC通讯的配置案例
智控YC-PNM-EIPProfinet转EtherNet/IP专业通讯网关应运而生,成为实现二者高效数据通讯的核心枢纽。 在某大型自动化生产车间,为优化电机驱动控制流程,提升生产效率,需要实
通过标准化数据通路来实现数据共享
标准化的数据接入与读取接口。
标准化数据通路的定义和实现
标准化数据通路是为各种业务场景提供的跨应用的数据接入与读取通路,它可以暂存应用需
发表于 06-17 06:57
STM32与机智云连接实现步骤与技巧(下篇):机智云代码移植与优化
在《STM32与机智云连接实现步骤与技巧(上篇)》中,我们介绍了硬件连接和通信协议配置。本篇将重点讲解如何将机智云相关代码移植到STM32,完成数据
不用联网不用编程,PLC通过智能网关快速实现HTTP协议JSON格式与MES等系统平台双向数据通讯
进行解析后将数据写入到PLC,实现PLC与HTTP服务端双向通讯;作为服务端时根据客户端URL中的路径查找所配置的数据,打包成JSON文件后
如何实现不同品牌多网段PLC数据通讯
,网段为192.168.2.x。随着工厂智能化管理的推进,需要将所有PLC的数据进行集中采集与分析,以实现生产过程的优化控制和高效管理。但由于不同品牌PLC的协议差异,以及网段的不同,导致数据通讯难以直接
STM32H747I DSI模块采用一个数据通道无法显示图片怎么解决?
的是STM32H747I-DISCO,显示屏采用的是MB1166-A09。
大佬们能不能提供一些思路,应该怎么实现一个数据通道通信?感激!
发表于 03-07 08:11
使用stm32控制ads8331采集,ADS采集的数据通道会错位,为什么?
使用stm32控制ads8331采集,根据我们的方案,使用过程中STM32会被软复位。这之前先给ADS8331软复位,然后STM32再软复位。ADS8331重新开始采集
发表于 02-10 07:13
IGT-DSER系列PLC通讯智能网关的配置说明(免编程的多台PLC之间通讯篇)
错误处理机制。
启动参数管理软件(在附件中),通过[功能]/[PLC之间实时通讯],切换到数据通讯表配置编辑参数编辑窗口,如下图,每一个任务条目包含两行数据,分别为目标设备和
发表于 01-24 11:59
维爱普 数据通讯设备稳定性:滤波器的核心作用
在当今这个信息爆炸的时代,数据通讯设备已经成为我们日常生活中不可或缺的一部分。无论是智能手机、电脑,还是网络通信基站、数据中心,这些设备都在不断地传输、处理着海量的数据。然而,在
安信可智能无线数据通讯Ra-09-DTU
Ra-09-DTU 是由安信可科技开发的一款智能无线数据通讯DTU,采用Ra-09 LoRa 模组,利用 LoRa 无线技术可用于超长距离扩频通信。其芯片 STM32WLE5CCU6 是通用

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