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

发布时间:2023-08-03  

在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 rn",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!rn");

  

  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值:%drn 电压值:%f V",adc,vol_led);  //打印ad值和电压值

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

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

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


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


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>