STM32
直播中

的乏味而

13年用户 801经验值
私信 关注
[问答]

详解STM32F103R8T6芯片所有IO口配置

如何利用STM32F103R8T6芯片去配置LED呢?

如何利用STM32F103R8T6芯片去配置BEEP呢?

回帖(2)

朱艳丽

2021-12-8 10:26:14



所有IO口配置,芯片:STM32F103R8T6
  一、配置LED

  /****************************
函数名称:LED_Config
函数作用:LED初始化
管脚:
LED1 PB0
LED2 PB1
****************************/
LED.c
寄存器:

#include "led.h"
void LED_Config(void)
{
        RCC->APB2ENR |= (1 << 3);//GPIOB       
        GPIOB->CRL &= ~(0XF <<0);//清零操作
        GPIOB->CRL |= (0X3 << 0);       
        GPIOB->CRL &= ~(0XF << 4);//清零操作
        GPIOB->CRL |= (0X3 << 4);//模式配置:通用推挽输出


        LED1(0);
        LED2(0);
}


库函数:


void LED_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure = {0};
        //时钟使能
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//PB0
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//PB1
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速率
        GPIO_Init(GPIOB,&GPIO_InitStructure);//结构体初始化
        //初始化状态
        GPIO_SetBits(GPIOB,GPIO_Pin_0);
        GPIO_SetBits(GPIOB,GPIO_Pin_1);


}


LED.h


#ifndef _LED_H_
#define _LED_H_


#include "stm32f10x.h"


#define LED1(x) (x)?(GPIO_ResetBits(GPIOB,GPIO_Pin_0)):(GPIO_SetBits(GPIOB,GPIO_Pin_0))
#define LED2(x) (x)?(GPIO_ResetBits(GPIOB,GPIO_Pin_1)):(GPIO_SetBits(GPIOB,GPIO_Pin_1))


void LED_Config(void);
#endif


二、配置KEY
/****************************
函数名称:KEY_Config
函数作用:按键初始化
管脚:KEY1 PA0
****************************/
KEY.c
寄存器:


#include "key.h"


void KEY_Config(void)
{
        RCC->APB2ENR |= (1 << 2);//使能GPIOA       
        GPIOA->CRL &= ~(0XF << 0);
        GPIOA->CRL |= (0X4 << 0);
}


/****************************
函数名称:KEY_GetVal
函数作用:按键初始化
函数参数:无
函数返回值:
                0                无按键按下
                1                KEY1按下
管脚:PA0
****************************/
uint8_t KEY_GetVal(void)
{
        uint8_t Key_Val = 0;
       
        if(!KEY1)//如果按键按下
        {
                Delay_nop_nus(15);
                if(!KEY1)//真的有人按下按键
                {
                        while(!KEY1);//松手检测
                        Key_Val = 1;
                }
        }
        return Key_Val;
}


库函数:


void KEY_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure = {0};
        //时钟使能
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
       
        //模式配置
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//设置浮空输入模式
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//选中管脚 0
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//最高输出速率 50MHz
        GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化结构体
}


KEY.h


#ifndef _KEY_H_
#define _KEY_H_


#include "stm32f10x.h"


#include "systick.h"
#include "delay.h"
#define KEY1 (GPIOA->IDR & (1 << 0))
//#define KEY1 (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))


void KEY_Config(void);
uint8_t KEY_GetVal(void);


#endif


三、配置DELAY
Delay.c


#include "delay.h"




/****************************
函数名称:Delay_nop_1us
函数作用:延时1微妙
****************************/
void Delay_nop_1us(void)
{
        __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
        __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
        __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
        __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
        __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
        __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
        __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
        __nop();__nop();
}


/****************************
函数名称:Delay_nop_nus
函数作用:延时n微妙
函数参数:time         延时时间
****************************/
void Delay_nop_nus(uint32_t time)
{
        while(time--)
                Delay_nop_1us();
}


Delay.h


#ifndef _DELAY_H_
#define _DELAY_H_


#include "stm32f10x.h"


#define Delay_nop_nms(x) Delay_nop_nus(x*1000)


void Delay_nop_nus(uint32_t time);


#endif


四、配置BEEP
BEEP.c
寄存器
/****************************
函数名称:BEEP_Config
函数作用:蜂鸣器初始化
管脚:BEEP PA1
****************************/


#include "BEEP.h"
void BEEP_Config(void)
{
        RCC->APB2ENR |= (1<<2);//GPIOC时钟使能       
        GPIOA->CRL &= ~(0XF << 4);//清零操作
        GPIOA->CRL |= (0X3 << 4);//模式配置:通用推挽输出
       
        BEEP(0);
}


库函数


void BEEP_BspConfig(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;//GPIO结构体
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//打开GPIOA时钟
        GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//工作模式为通用推挽输出
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;//选择工作管脚
        GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//选择工作速率
        GPIO_Init(GPIOA,&GPIO_InitStruct);
       
        GPIO_ResetBits(GPIOA,GPIO_Pin_1);//初始状态关闭蜂鸣器
}


BEEP.h


#ifndef _BEEP_H_
#define _BEEP_H_
#include "stm32f10x.h"


#define BEEP(x) (x)?(GPIOA->ODR |= (1 << 1)):(GPIOA->ODR &= ~(1 << 1))


//#define BEEP(X) (X)?(GPIO_SetBits(GPIOA,GPIO_Pin_1)):(GPIO_ResetBits(GPIOA,GPIO_Pin_1))


void BEEP_BspConfig(void);
#endif


五、配置USART
USART.c
寄存器


#include "usart.h"


/****************************
函数名称:USART_Config
函数作用:串口初始化
引脚: PA9   RX
          PA10  TX
****************************/


void USART_Config(uint32_t brr)
{
        float USARTDIV = 0.0;
        int DIV_Mantissa=0,DIV_Fraction=0;
       
        //1)        时钟使能—GPIOA、USART1
        RCC->APB2ENR |= (1 << 2)|(1 << 14);
       
        //2)        GPIO模式配置
        GPIOA->CRH &= ~(0XFF << 4);
       
        //PA9 复用推挽输出
        GPIOA->CRH |= (0XB << 4);


        //PA10 浮空输入
        GPIOA->CRH |= (0X4 << 8);       


        //3)        串口配置
        USART1->CR1 &= ~(1 << 12);        //一个起始位,8个数据位
        USART1->CR1 &= ~(1 << 10);        //禁止校验控制
        USART1->CR1 &= ~(0X3 << 2);//接收器、发送器先清0
        USART1->CR1 |= (0X3 << 2);        //接收器、发送器
        USART1->CR2 &= ~(0X3 << 12);//1个停止位
        //4)        波特率配置
        USARTDIV = (72000000.0)/(16*brr);//468.75
        DIV_Mantissa = (int)USARTDIV;//得到468
        DIV_Fraction = (USARTDIV-DIV_Mantissa)*16;//小数部分左移4位
        USART1->BRR = (DIV_Mantissa<<4)|DIV_Fraction;
        //USART1->BRR=0x1D4C
        //5)        使能串口
        USART1->CR1 |= (1 << 13);        //USART模块使能               
}


/****************************
函数名称:fputc
函数作用:USART1重定向函数
****************************/
int fputc(int c, FILE *stream)
{
        while((USART1->SR & (1 << 6)) == 0);
        USART1->DR = c;
        return c;
}


/****************************
函数名称:USART_Ech0
函数作用:串口回显
****************************/


void USART_Ech0(void)
{
  u8 data=0x00;
       
//读数据
        while((USART1->SR & (1 << 5)) == 0);//状态寄存器,读数据寄存器非空
        data=USART1->DR;//数据寄存器


        //写数据
        while((USART1->SR & (1 << 6)) == 0);//等待上次数据发送完成
        USART1->DR=data;
}       


库函数:


void USART1_Config(u16 brr)
        {
        /********结构体********/
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
       
        /********时钟使能********/
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);       
       
        /********GPIO配置********/
        //USART1_TX   GPIOA.9
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9


        //USART1_RX          GPIOA.10初始化
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
       
        /********USART1串口配置********/
        USART_InitStructure.USART_BaudRate=brr;//波特率配置
        USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件数据流控制
        USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx ;//收发模式
        USART_InitStructure.USART_Parity=USART_Parity_No;//无奇偶校验位
        USART_InitStructure.USART_StopBits=USART_StopBits_1;//停止位选择1
        USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长为8位数据格式
       
        /********USART1串口使能配置********/
                USART_Init(USART1, &USART_InitStructure); //初始化串口1
}


/****************************
函数名称:fputc
函数作用:USART1重定向函数
****************************/
int fputc(int c, FILE *stream)
{
        while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
        USART_SendData(USART1,c);
        return c;
}


/****************************
函数名称:USART_Ech0
函数作用:串口回显
函数参数:无
函数返回值:无
创建时间:2020.08.14
修改时间:2020.08.14
****************************/
void USART_Ech0(void)
{
  u8 data=0x00;
        while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == 0);//接收数据完成
        data = USART_ReceiveData(USART1);
        while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == 0);//发送数据
        USART_SendData(USART1,data);       


}


/****************************
函数名称:USART1_Send_Byte
函数作用:串口发送一个字节
****************************/
void USART1_Send_Byte(unsigned char byte)  
{
        USART_SendData(USART1, byte);      
        while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);                 
}




/****************************
函数名称:UART1_Send_Str
函数作用:串口发送发送字符串函数
****************************/
void UART1_Send_Str(unsigned char *s)
{
        unsigned char i=0;  
        while(s!='')
        {
                USART_SendData(USART1,s);      
                while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);  
        }
}




/****************************
函数名称:UART1_Send_Array
函数作用:串口发送数组 一是数组(的数据) 二是数组长度1-255
****************************/
void UART1_Send_Array(unsigned char send_array[],unsigned char num)
{
        unsigned char i=0;
        while(i         {               
                USART_SendData(USART1,send_array);     
                while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);  
                i++;         
        }       
}


USART.h


#ifndef _USART_H_
#define _USART_H_


#include "stm32f10x.h"
#include "stdio.h"


void USART1_Config(u16 brr);
void USART1_Send_Byte(unsigned char byte) ;


#endif


六、配置EXTI
EXTI.c
寄存器


/****************************
函数名称:EXTI0_Config
函数作用::外部中断0初始化(寄存器)
****************************/
#include "exti.h"


void EXTI0_Config(void)
{
        //第一步:时钟使能—AFIO
        RCC->APB2ENR |= (1 << 0);
       
        //第二步:配置按键—调用KEY初始化
        KEY_Config();
       
        //第三步:配置外部中断线—AFIO
        AFIO->EXTICR[0] &= ~(0XF << 0);        //Line0配置为PA
       
        //第四步:中断触发源—EXTI
        EXTI->IMR |= (1 << 0);        //开Line0中断
        EXTI->RTSR |= (1 << 0);        //上升沿触发
       
        //第五步:配置中断优先级
//        NVIC_SetPriorityGrouping(5);//一般写在主函数开始 分组
        NVIC_SetPriority(EXTI0_IRQn,0);//0000 优先级
        NVIC_EnableIRQ(EXTI0_IRQn);
}


库函数


void EXTI0_BspConfig(void)       
{
/********结构体********/
        EXTI_InitTypeDef EXTI_InitStructure={0};
/********时钟使能********/
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//第二步:配置按键—调用KEY初始化
        KEY_Config();
//第三步:配置外部中断线—AFIO
        GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//EXTI中断事件线选择


        //第四步:中断触发源—EXTI
        EXTI_InitStructure.EXTI_Line=EXTI_Line0;
        EXTI_InitStructure.EXTI_LineCmd=ENABLE;//时钟使能
        EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//EXTI模式选择(中断:Interrupt)
        EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising_Falling;//EXTI边沿触发事件 上,下沿
        EXTI_Init(&EXTI_InitStructure);//初始化
//第五步:配置中断优先级
        NVIC_InitTypeDef NVIC_InitStructure={0};
        NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//占先
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//次级
        NVIC_Init(&NVIC_InitStructure);
}


EXTI.h


#ifndef _EXTI_H_
#define _EXTI_H_


#include "stm32f10x.h"
#include "key.h"


#define EXTI0_LIB 1
void EXTI0_Config(void);
void EXTI0_BspConfig(void);


#endif


七、配置TIM
TIM.c
寄存器


/****************************
函数名称:TIM3_CH3_Config
函数作用:TIM3_CH3初始化
管脚:
LED1:PB0
****************************/
void TIM3_CH3_Config(uint32_t psc,uint32_t arr)
{  
// 时钟使能: GPIOB TIM3
  RCC->APB2ENR |=(1<<3);//IO端口B时钟开启。
        RCC->APB1ENR |=(1<<1);//定时器3时钟开启
       
// GPIO 模式配置: 复用推挽输出
        GPIOB->CRL &=~(0XF<<4);//先清0
        GPIOB->CRL |=(0XB<<4);       
// 定时器基本功能: 预分频、 重装载、 计数方式、 计数器
        TIM3->CR1 &=~(0X3<<8);//分频因子1
        TIM3->CR1 |=(1<<7);//自动重装载
        TIM3->CR1 &=~(1<<4);//向上计数
        TIM3->PSC=psc-1;//预分频
        TIM3->ARR=arr-1;//重装载值
        TIM3->CNT=0;//计数器清零
// 定时器输出比较: PWM1 有效电平
        TIM3->CCMR2 &=~(0X3<<8);//通道4配置为输出
        TIM3->CCMR2 &=~(0X7<<12);//先清0
        TIM3->CCMR2 |=(0X6<<12);//通道4 PWM1
        TIM3->CCER |=(1<<13);//通道4 低电平有效
        TIM3->CCER |=(1<<12);//通道4 输出到管脚
        TIM3->CCR4 = arr/2;//赋初值


        TIM3->CR1 |=(1<<0);//使能TIM3定时器
}
库函数


void TIM3_CH3_Config(uint32_t psc,uint32_t arr)
{  
  /*使能GPIOB、TIM3时钟*/
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM3时钟
  //定义结构体
  GPIO_InitTypeDef GPIO_InitStructure={0};//定义GPIO初始化结构体
        TIM_TimeBaseInitTypeDef TIM_InitStructure={0};//定义TIM3基础的初始化结构体
        TIM_OCInitTypeDef TIM_OCInitStructure={0};//定义TIM3_CH3输出模式的结构体
   //GPIO配置
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//模式设置为复用推挽输出
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;//端口为0
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出速率为50Mhz
        GPIO_Init(GPIOB,&GPIO_InitStructure);//GPIO设置初始化函数,将设置设定在GPIOB端口
        //定时器配置
        TIM_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//分频因子
        TIM_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
        TIM_InitStructure.TIM_Period=arr-1;//重装载
        TIM_InitStructure.TIM_Prescaler=psc-1;//预分频的值
        TIM_TimeBaseInit(TIM4,&TIM_InitStructure);//初始化TIM3基本设置函数
        //配置定时器输出模式
        TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//选择PWM模式
        TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_Low;//低电平有效
        TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//设定输出比较状态使能
        TIM_OCInitStructure.TIM_Pulse=arr/2;//比较寄存器中的值       
        TIM_OC4Init(TIM3,&TIM_OCInitStructure);//初始化TIM3_CH3输出设置函数
       
        TIM_Cmd(TIM3,ENABLE);//使能TIM3定时器
}
TIM.h


#ifndef _TIM_H_
#define _TIM_H_


#include "stm32f10x.h"
#include "stdio.h"


void TIM3_CH3_Config(uint32_t psc,uint32_t arr);


#endif
举报

李宛蔓

2021-12-8 10:26:17
八、配置SPI
SPI.c
寄存器


/****************************
函数名称:SPI1_Config 串行外设接口
函数作用:SPI1初始化
管脚:                PA4:通用推挽 CS
                        PA5:复用推挽 SCK
                        PA6:浮空输入 MISO
                        PA7:复用推挽 MOSI
****************************/
void SPI1_Config(void)
{


        //时钟使能GPIOA SPI1
        RCC->APB2ENR |= (1 << 2)|(1 << 12);
       
        //配置GPIO口
        GPIOA->CRL &= ~((u32)0XFFFF << 16);//16-28位清0
        GPIOA->CRL |= ((u32)0XB4B3 << 16);//1011     0100     1011      0011
                                        //复用推挽  浮空输入 复用推挽  通用推挽
       
        //SPI1模式配置
        SPI1->CR1 = 0;            // 每一位都清0
        SPI1->CR1 |= (0X3 << 8);        //NSS软件触发
        SPI1->CR1 |= (0X1 << 2);        //主设备
        SPI1->CR1 |= (0X1 << 6);        //SPI1使能


}
/****************************
函数名称:SPI1_ReadWrite_Data
函数作用:SPI1读写数据
****************************/
uint8_t SPI1_ReadWrite_Data(uint8_t Data)
{
        while((SPI1->SR & (1 << 1)) == 0);   //发送缓冲为空
        SPI1->DR = Data;                     //把数据写入数据寄存器
        while((SPI1->SR & (1 << 0)) == 0);   //接收缓冲非空。
        return (SPI1->DR);                   //返回数据寄存器中的数据
}
寄存器


void SPI1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
SPI_InitTypeDef SPI_InitStructure = {0};

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1,ENABLE);

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//通用推挽 CS
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽 SCK
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入 MISO
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽 MOSI
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);


SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;
SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;
SPI_InitStructure.SPI_CRCPolynomial=7;
SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;
SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;
SPI_InitStructure.SPI_Mode=SPI_Mode_Master;
SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;
SPI_Init(SPI1,&SPI_InitStructure);
SPI_Cmd(SPI1,ENABLE);

}


uint8_t SPI_ReadWriter_Data(uint8_t data)
{
        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == 0);//等待发送缓冲为空
        SPI_I2S_SendData(SPI1,data);                             //发送数据
        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==0); //等待接收缓冲非空
        return SPI_I2S_ReceiveData(SPI1);                        //接收数据
}
SPI.h


#ifndef _SPI1_H_
#define _SPI1_H_


#include "stm32f10x.h"


void SPI1_Config(void);
uint8_t SPI1_ReadWrite_Data(uint8_t Data);


#endif
九、配置ADC
ADC.c
寄存器


/****************************
函数名称:ADC1_IN3_Config
函数作用:ADC1通道10初始化
端口:PC0
****************************/
void ADC1_IN10_Config(void)
{


        /*第1步,使能GPIOC、ADC1时钟*/
        RCC->APB2ENR |= (0X1 << 4);                        //使能GPIOC端口时钟
        RCC->APB2ENR |= (0X1 << 9);                        //使能ADC1时钟
/*第2步,GPIOC-0端口配置*/
        GPIOC->CRL &= ~(0XF << 0);                         //设置GPIOC-0为模拟输入模式
       
/*第3步,设置ADC预分频以及采样周期*/
        RCC->CFGR &= ~(0X3 << 14);
        RCC->CFGR |= (0X2 << 14);                        //设置ADC预分频6分频为12MHz,因为超过14Mhz会不准
       
        ADC1->SMPR1 &= ~(0X7 << 0);
        ADC1->SMPR1 |= (0X7 << 0);                        //设置10通道的采样周期为最大,这样比较精确但是时间会长一点
/*第4步,设置ADC1基本设置*/
        ADC1->CR1 &= ~(0XF << 16);                        //选择独立模式(非双模式)
        ADC1->CR1 &= ~(0X1 << 8);                        //关闭扫描模式
       
        ADC1->CR2 |= (0X1 << 20);                        //规则通道-使用外部事件启动转换。
        ADC1->CR2 |= (0X7 << 17);                        //选择启动规则通道组转换的外部事件(软件触发)
        ADC1->CR2 &= ~(0X1 << 11);                        //存储对其方式选择右对齐
        ADC1->CR2 |= (0X1 << 1);                        //选择连续转换模式
/*第5步,设定规则序列寄存器的长度,和位置所对应的通道数*/
        ADC1->SQR1 &= ~(0XF << 20);                        //定义规则序列长度为1
        ADC1->SQR3 &= ~(0X1F << 0);
        ADC1->SQR3 |= (10 << 0);                        //定义规则序列中第一个转换代表ADC1_10通道
/*第6步,使能ADC1定时器,并进行初始化复位*/
        ADC1->CR2 |= (0X1 << 0);                        //开启ADC并启动转换
        ADC1->CR2 |= (0X1 << 3);
        while(ADC1->CR2 & (0X1 << 3));                //开启复位校准
        ADC1->CR2 |= (0X1 << 2);
        while(ADC1->CR2 & (0X1 << 2));                //开启A/D校准
        ADC1->CR2 |= (0X1 << 22);                        //开始转换规则通道(必须开启定时器后开始,可以在复位之前)
}
库函数


void ADC1_IN10_Config(void)
{


  /*第1步,使能GPIOC、ADC1时钟*/
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能GPIOC端口时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//使能ADC1时钟
       
  /*第二步,设置ADC分频*/
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADC分频为6分频 12MHz,不能超过14MHz
        /*第三步,GPIOC-0初始化*/
  GPIO_InitTypeDef GPIO_InitStructure={0}; //GPIOC-0端口初始化
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟输入模式
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;//管脚0
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//最高速运行
        GPIO_Init(GPIOC, &GPIO_InitStructure);        //把参数传入初始化参数
        /*第三步,配置ADC基本配置*/
        ADC_InitTypeDef ADC_InitStructure={0};  //ADC基本配置结构体变量
        ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//连续模式
        ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//存储方式选择右对齐方式
        ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//软件触发模式
        ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//ADC工作在独立模式
        ADC_InitStructure.ADC_NbrOfChannel=1;//顺序转换通道数目为1
        ADC_InitStructure.ADC_ScanConvMode=DISABLE; //扫描模式关闭
        ADC_Init(ADC1, &ADC_InitStructure);//将参数传入初始化函数
        /*第四步,设置规则组的顺序,以及采样周期*/
        ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_239Cycles5);
        //将ADC1 10通道放在规则组第一个,采样周期为最大
       
/*第五步,使能ADC、校准、使能规则通道组转换*/
  ADC_Cmd(ADC1,ENABLE);//ADC使能
  ADC_ResetCalibration(ADC1);//开启ADC并启动转换 上电状态
        while(ADC_GetResetCalibrationStatus(ADC1) == 1);                //开启复位校准
        ADC_StartCalibration(ADC1);                                                                //
        while(ADC_GetCalibrationStatus(ADC1) == 1);                                //开启A/D校准
        ADC_SoftwareStartConvCmd(ADC1,ENABLE);  //开始转换规则通道


}
ADC.h


#ifndef _ADC_H_
#define _ADC_H_


#include "stm32f10x.h"
#include "stdio.h"


void ADC1_IN10_Config(void);


#endif


十、配置DMA
DMA.c
寄存器


/****************************
函数名称:DMA_Config
函数作用:DMA初始化
端口:PC0 1 2
****************************/
uint16_t DMA_Buf[3] = {0};
void DMA_Config(void)
{


         /*第1步,使能GPIOC、ADC1 DMA1时钟*/
        RCC->APB2ENR |= (1 << 4)|(1 << 9);//使能GPIOC端口时钟,//使能ADC1时钟
        RCC->AHBENR |= (1 << 0);//使能DMA1
        //GPIO模式配置:模拟输入
        GPIOC->CRL &= ~(0XFFF << 0);//GPIOC、ADC1 DMA1 0000 0000 0000
        //时钟预分频:CLK、采样时间
        RCC->CFGR &= ~(0X3 << 14);  //先清0
        RCC->CFGR |= (0X2 << 14);                        //设置ADC预分频6分频为12MHz,因为超过14Mhz会不准
        ADC1->SMPR1 |= (0X7 << 0);        //IN10——239.5周期
        ADC1->SMPR1 |= (0X7 << 3);        //IN11——239.5周期
        ADC1->SMPR1 |= (0X7 << 6);        //IN12——239.5周期
        //ADC配置:CR1 CR2
        ADC1->CR1 &= ~(0XF << 16);        //独立模式
        ADC1->CR1 |= (0X1 << 8);                //打开扫描
        ADC1->CR2 |= (0X1 << 20);                        //规则通道-使用外部事件启动转换。
        ADC1->CR2 |= (0X7 << 17);                        //选择启动规则通道组转换的外部事件(软件触发)
        ADC1->CR2 &= ~(0X1 << 11);        //存储对其方式选择右对齐
        ADC1->CR2 |= (1 << 1);                        //选择连续转换模式
        //ADC通道配置:规则转换顺序
        ADC1->SQR1 &= ~(0XF << 20);       
        ADC1->SQR1 |= (0X2 << 20);        //3个转换(0010)
        //111 1111 1111 1111
        //12 11 10     01100 01011 01010=ADC1->SQR3 |= (0X316A << 0);
        ADC1->SQR3 &= ~(0X7FFF << 0);//规则序列中的3个转换15位清0
        ADC1->SQR3 |= (10 << 0);//规则序列中的第1个转换写10
        ADC1->SQR3 |= (11 << 5);//规则序列中的第2个转换写11
        ADC1->SQR3 |= (12 << 10);//规则序列中的第3个转换写12
        //开DMA
        ADC1->CR2 |= (1 << 8);//使用DMA模式
       
//DMA配置
        DMA1_Channel1->CPAR = (u32)(&(ADC1->DR));                //外设地址
        DMA1_Channel1->CMAR = (u32)DMA_Buf;                                        //存储器地址
        DMA1_Channel1->CNDTR = 3;                                                                                //3个转换数据
        DMA1_Channel1->CCR = 0;                     //全部清0
        DMA1_Channel1->CCR |= (0X3 << 12);                                        //优先级最高
        DMA1_Channel1->CCR |=        (0X5 << 8);                                                //01 01外设&存储器数宽:16位
        DMA1_Channel1->CCR |=        (0X2 << 6);                                                //增量:外设不增,存储器增
        DMA1_Channel1->CCR |=        (0X1 << 5);                                                //循环模式
        DMA1_Channel1->CCR &=        ~(0X1 << 4);                                        //外设到存储器
       
        //使能
        DMA1_Channel1->CCR |=        (0X1 << 0);//通道开启
       
        ADC1->CR2 |= (1 << 0);                        //开启ADC并启动转换
        ADC1->CR2 |= (1 << 3);
        while(ADC1->CR2 & (1 << 3));//开启复位校准
        ADC1->CR2 |= (1 << 2);
        while(ADC1->CR2 & (1 << 2));        //开启A/D校准
        ADC1->CR2 |= (1 << 22);                //开始转换规则通道(必须开启定时器后开始,可以在复位之前)


}


库函数


void DMA_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure = {0};
        ADC_InitTypeDef ADC_InitStructure = {0};
        DMA_InitTypeDef DMA_InitStructure = {0};
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);//使能GPIOC端口时钟,使能ADC1时钟
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//使能DMA1
       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入模式
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2;//管脚0,1,2
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//最高速运行
        GPIO_Init(GPIOC,&GPIO_InitStructure);//把参数传入初始化参数
       
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADC分频为6分频 12MHz,不能超过14MHz
       
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//连续模式
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//存储方式选择右对齐方式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发模式
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC工作在独立模式
        ADC_InitStructure.ADC_NbrOfChannel = 3;//顺序转换通道数目为3
        ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描模式打开
        ADC_Init(ADC1,&ADC_InitStructure);//将参数传入初始化函数
       
        ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_239Cycles5);//将ADC1 10通道放在规则组第一个,采样周期为最大
        ADC_RegularChannelConfig(ADC1,ADC_Channel_11,2,ADC_SampleTime_239Cycles5);//将ADC1 11通道放在规则组第二个,采样周期为最大
        ADC_RegularChannelConfig(ADC1,ADC_Channel_12,3,ADC_SampleTime_239Cycles5);//将ADC1 12通道放在规则组第三个,采样周期为最大
        ADC_DMACmd(ADC1,ENABLE);
       
        DMA_InitStructure.DMA_BufferSize=3;//数据数目
        DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;//从外设到内存
        DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//DMA 通道1没有设置为内存到内存传输
        DMA_InitStructure.DMA_MemoryBaseAddr=(u32)DMA_Buf;//存储器地址
        DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord ;//存储器数据宽度
        DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable ;//存储器递增
        DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;//模式选择
        DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)(&(ADC1->DR));//外设地址
        DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//外设数据宽度
  DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设递增
        DMA_InitStructure.DMA_Priority=DMA_Priority_VeryHigh ;//最高优先级
        DMA_Init(DMA1_Channel1,&DMA_InitStructure);
       
        DMA_Cmd(DMA1_Channel1,ENABLE);//使能DMA
        ADC_Cmd(ADC1,ENABLE);
        ADC_ResetCalibration(ADC1);
        while(ADC_GetResetCalibrationStatus(ADC1));
        ADC_StartCalibration(ADC1);
        while(ADC_GetCalibrationStatus(ADC1));
        ADC_SoftwareStartConvCmd(ADC1,ENABLE);
       
}


DMA.h


#ifndef _DMA_H_
#define _DMA_H_


#include "stm32f10x.h"
#include "stdio.h"


extern uint16_t DMA_Buf[3];


void DMA_Config(void);


#endif
举报

更多回帖

×
20
完善资料,
赚取积分