实验例子-代码
GPIO实验
例1:GPIO-MOTO实验
当按下KEY1键时,双色红灯闪烁且电机正转,当按下当KEY2键时,双色绿灯闪烁且电机反转,当按下KEY3键时,双色灯灭,电机停止。
#include "stm32f10x_conf.h"
#define KEY1 GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11)
#define KEY2 GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_12)
#define KEY3 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)
#define IA(x) ((x) ? (GPIO_SetBits(GPIOB, GPIO_Pin_8)) : (GPIO_ResetBits(GPIOB, GPIO_Pin_8)))
#define IB(x) ((x) ? (GPIO_SetBits(GPIOB, GPIO_Pin_9)) : (GPIO_ResetBits(GPIOB, GPIO_Pin_9)))
#define LEDR(x) ((x) ? (GPIO_SetBits(GPIOB, GPIO_Pin_1)) : (GPIO_ResetBits(GPIOB, GPIO_Pin_1)))
#define LEDG(x) ((x) ? (GPIO_SetBits(GPIOB, GPIO_Pin_2)) : (GPIO_ResetBits(GPIOB, GPIO_Pin_2)))
/*********************************************
*函数名称:void Delayms(void)
*功能说明:简单延时N ms
**********************************************/
void Delayms(uint16_t N)
{
uint32_t i;
for (i = 0; i < (8000 * N); i++);
}
/*********************************************
*函数名称:void GPIO_MOTO_Init(void)
*功能说明:初始化GPIO(LED、MOTO、KEY)
**********************************************/
void GPIO_MOTO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure); /*初始化GPIOD端口PD11=KEY1,PD12=KEY2上拉输入,10MHz*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStructure); /*初始化GPIOC端口PC13=KEY3上拉输入,10MHz*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure); /*初始化GPIOD端口PD2、3、4、7 10MHz推挽输出*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure); /*初始化GPIOB端口PB1=RED,PB2=GREEN,PB8=IA,PB9=IB 10MHz推挽输出*/
/*---------初始化状态指示灯灭OFF------------*/
IA(0);
IB(0); /* 电机停止 */
LEDR(0);
LEDG(0); /* 双色指示灯全灭 */
GPIO_SetBits(GPIOD, GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7);/* 4只指示灯灭 */
}
#define n 200 /*延时时间常数*/
int main(void) {
u8 KEY = 0;
SystemInit(); /*系统初始化*/
GPIO_MOTO_Init(); /*GPIO初始化*/
while (1)
{
if (KEY1 == 0) KEY = 1;
if (KEY2 == 0) KEY = 2;
if (KEY3 == 0) KEY = 3;
switch (KEY)
{
case 1: /* 电机正转 */
IA(1); /* PB8=IA=1 */
IB(0); /* PB9=IB=0 */
LEDR(1); /* PB1=1 红灯闪烁 */
Delayms(n);
LEDR(0);
Delayms(n);
LEDG(0); /* PB2=1 绿灯灭 */
break;
case 2: /* 电机反转 */
IA(0); /* PB9=IB=1 */
IB(1); /* PB8=IA=0 */
LEDR(0); /* PB1=0 红灯灭 */
LEDG(1); /* PB2=1 绿灯闪烁 */
Delayms(n);
LEDG(0);
Delayms(n);
break;
case 3: /* 电机停止 */
IA(0); /* PB9=IB=0 */
IB(0); /* PB8=IA=0 */
LEDR(0); /* PB1=0 红灯灭 */
LEDG(0); /* PB2=1 绿灯灭 */
break;
}
}
}
例2:GPIO简单交互
当按KEY1(PD11)键时,让LED1(PD2)闪烁;当按KEY2(PD12)键时,让LED2(PD3)闪烁;当按KEY3(PC13)键时,让LED3(PD4)闪烁;当按KEY4(PA0)键时,让LED4(PD7)闪烁;当同时按下KEY1和KEY2时,四个LED发光管全亮。
#define LED1(x) ((x)? GPIO_SetBits(GPIOD,(1<<2)) : GPIO_ResetBits(GPIOD,(1<<2)))
#define LED2(x) ((x)? GPIO_SetBits(GPIOD,(1<<3)) : GPIO_ResetBits(GPIOD,(1<<3)))
#define LED3(x) ((x)? GPIO_SetBits(GPIOD,(1<<4)) : GPIO_ResetBits(GPIOD,(1<<4)))
#define LED4(x) ((x)? GPIO_SetBits(GPIOD,(1<<7)) : GPIO_ResetBits(GPIOD,(1<<7)))
#define KEY1 (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11))
#define KEY2 (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_12))
#define KEY3 (GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13))
#define KEY4 (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))
unit16_t key = 0;
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/*KEY1(PD11)和KEY2(PD12)引脚配置为上拉输入*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;/*KEY3(PC13)引脚配置为上拉输入*/
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;/*KEY4(PA0)引脚配置为上拉输入*/
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*---------初始化状态四个LED全OFF------------*/
LED1(1);
LED2(1);
LED3(1);
LED4(1);
}
void main()
{
SystemInit();
GPIO_Configuration();
while(1)
{
if(KEY1 == 0) key = 1;
if(KEY2 == 0) key = 2;
if(KEY3 == 0) key = 3;
if(KEY4 == 0) key = 4;
if(KEY1 == 0 && KEY2 == 0) key = 5;
switch(key)
{
case 1:
LED2(1); LED3(1); LED4(1);
LED1(1); Delay(); LED1(0); break;
case 2:
LED1(1); LED3(1); LED4(1);
LED2(1); Delay(); LED2(0); break;
case 3:
LED1(1); LED2(1); LED4(1);
LED3(1); Delay(); LED3(0); break;
case 4:
LED2(1); LED3(1); LED4(1);
LED1(1); Delay(); LED1(0); break;
case 5:
LED1(0); LED2(0); LED3(0); LED4(0);
break;
default:
LED1(1); LED2(1); LED3(1); LED4(1);
break;
}
}
}
例3:GPIO 引脚中断
采用中断方式判断单个按键:当按下KEY1(PD11)时,让LED1(PD2)闪烁;当按下KEY2(PD12)时让LED2(PD3)闪烁;采用查询方式判断复合键:当同时按下KEY1和KEY2时,LED1和LED2发光管全灭。
#define LED1(x) ((x)? GPIO_SetBits(GPIOD,(1<<2)) : GPIO_ResetBits(GPIOD,(1<<2)))
#define LED2(x) ((x)? GPIO_SetBits(GPIOD,(1<<3)) : GPIO_ResetBits(GPIOD,(1<<3)))
#define KEY1 (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11))
#define KEY2 (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_12))
unit16_t Flag = 0;
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD , GPIO_PinSource11);/*PD11作为外部中断线*/
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD , GPIO_PinSource12);/*PD12作为外部中断线*/
/*---------初始化状态2个LED全OFF------------*/
LED1(1);
LED2(1);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /*使用优先级分组2*/
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn ;/*配置EXTI第15~10线的中断向量*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0 ;/*抢占优先级0*/
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /*子优先级1*/
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE ;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line11; /*PD11外部中断输入*/
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; /*下降沿触发*/
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = EXTI_Line12; /*PD12外部中断输入*/
EXTI_Init(&EXTI_InitStructure);
}
void EXTI15_10_IRQHandler() /* 中断服务程序 */
{
if(EXTI_GetITStatus(EXTI_Line11) != RESET)
{
Flag = 0x01;
EXTI_ClearITPendingBit(EXTI_Line11);
}
else if(EXTI_GetITStatus(EXTI_Line12) != RESET)
{
Flag = 0x2;
EXTI_ClearITPendingBit(EXTI_Line12);
}
}
int main()
{
SytemInit();
GPIO_Configuration();
NVIC_Configuration();
EXTI_Configuration();
while(1)
{
if(KEY1 == 0 && KEY2 == 0)
{
Flag = 0x03;
}
switch(Flag)
{
case 0x01:
LED2(1);
LED1(0); Delay(); LED1(1); Delay();
break;
case 0x02:
LED1(1);
LED2(0); Delay(); LED2(1); Delay();
break;
case 0x03:
LED1(1); LED2(1);
break;
default:
LED1(0); LED2(0);
break;
}
}
}
TIM实验
例1:TIM更新方式定时
定时器TIM1定时1秒,TIM2定时500ms,TIM3定时200ms,定时器到时分别使LED1、LED2和LED3改变状态(闪烁)
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = LED1_PIN | LED2_PIN | LED3_PIN | LED4_PIN ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LED5_PIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = BEEP_PIN ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*---------初始化状态四个LED全OFF------------*/
LED1(1);
LED2(1);
LED3(1);
LED4(1);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);/*使能TIM1时钟,因为TIM1和TIM8连接在APB2上*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3, ENABLE);/*使能TIM2/TIM3时钟,因为TIM2~TIM7连接在APB1上*/
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0 ;/*不能少!对于TIM1/TIM8高级定时器必须把重新计数清零,否则TIM1定时器不准确,利用它可以重新不同的定时次数达到不同定时*/
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 10*1000-1; //1000ms
TIM_TimeBaseStructure.TIM_Prescaler = SystemCoreClock/10000-1;//0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 10*500-1; //500ms
TIM_TimeBaseStructure.TIM_Prescaler = SystemCoreClock/10000-1;//0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 10*200-1; //200ms
TIM_TimeBaseStructure.TIM_Prescaler = SystemCoreClock/10000-1;//0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* TIM Interrupts enable */
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
/* TIM1/2/3 enable counter */
TIM_Cmd(TIM1, ENABLE);
TIM_Cmd(TIM2, ENABLE);
TIM_Cmd(TIM3, ENABLE);
}
u8 TP1=0,TP2=0,TP3=0;
void TIM1_UP_IRQHandler(void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) /*判断是否是更新中断*/
{
TIM_ClearITPendingBit(TIM1, TIM_IT_Update); /*清除中断标志*/
TP1++;
if (TP1&1) GPIO_ResetBits(GPIOD,GPIO_Pin_2); /* PD2=0(LED1亮)*/
else GPIO_SetBits(GPIOD,GPIO_Pin_2); /* PD2=1(LED1灭)*/
}
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) /*判断是否是更新中断*/
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); /*清除中断标志*/
TP2++;
if (TP2&1) GPIO_ResetBits(GPIOD,GPIO_Pin_3); /* PD3=0(LED2亮)*/
else GPIO_SetBits(GPIOD,GPIO_Pin_3); /* PD3=1(LED2灭)*/
}
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) /*判断是否是更新中断*/
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); /*清除中断标志*/
TP3++;
if (TP3&1) GPIO_ResetBits(GPIOD,GPIO_Pin_4); /* PD4=0(LED3亮)*/
else GPIO_SetBits(GPIOD,GPIO_Pin_4); /* PD4=1(LED3灭)*/
}
}
int main(void)
{
SystemInit();
GPIO_Configuration();
TIM_Configuration(); /* 初始化TIMx定时器 */
NVIC_Configuration();
LCD_Init(); /* LCD初始化 */
Welcome(); /* 显示主界面 */
LED1(1);LED2(1);LED3(1);LED4(1);
while(1)
{
/* 本例程,主循环体不做事情,全部在中断函数中让LED闪烁,可根据需要自行加功能代码*/
}
}
例2:TIM比较定时
定时器TIM3利用比较器1定时1秒让LED1闪烁,比较器2定时500ms,让LED2闪烁,比较器3定时200ms,让LED3闪烁,比较器4定时100ms让LED4闪烁
u16 CCR1_Val = 10*1000; /*定时1000ms*/
u16 CCR2_Val = 10*500; /*定时500ms*/
u16 CCR3_Val = 10*200; /*定时200ms*/
u16 CCR4_Val = 10*100; /*定时100ms*/
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period =65535;
TIM_TimeBaseStructure.TIM_Prescaler =(SystemCoreClock/10000)-1;/*预分频*/
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* Output Compare Timing Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; /*输出定时模式*/
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;/*输出禁止,这里仅比较,不输出*/
TIM_OCInitStructure.TIM_Pulse = CCR1_Val; /*比较脉冲个数*/
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
/* Output Compare Timing Mode configuration: Channel2 */
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
/* Output Compare Timing Mode configuration: Channel3 */
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
//TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
/* TIM Interrupts enable */
TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 |TIM_IT_CC4, ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = LED1_PIN | LED2_PIN | LED3_PIN | LED4_PIN ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LED5_PIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = BEEP_PIN ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*---------初始化状态四个LED全OFF------------*/
LED1(1);
LED2(1);
LED3(1);
LED4(1);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
extern u16 CCR1_Val;
extern u16 CCR2_Val;
extern u16 CCR3_Val;
extern u16 CCR4_Val;
void TIM3_IRQHandler(void)
{
uint16_t capture = 0;
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); /*是比较中断,清除中断标志*/
GPIOD->ODR ^= 1<<2; /*LED1(PD2)*/
capture = TIM_GetCapture1(TIM3); /*取当前计数值*/
TIM_SetCompare1(TIM3, capture + CCR1_Val); /*写新比较值到比较寄存器*/
}
else if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
GPIOD->ODR ^= 1<<3; /*LED2(PD3)*/
capture = TIM_GetCapture2(TIM3);
TIM_SetCompare2(TIM3, capture + CCR2_Val);
}
else if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
GPIOD->ODR ^= 1<<4; /*LED3(PD4)*/
capture = TIM_GetCapture3(TIM3);
TIM_SetCompare3(TIM3, capture + CCR3_Val);
}
else if (TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
GPIOD->ODR ^= 1<<7; /*LED4(PD7)*/
capture = TIM_GetCapture4(TIM3);
TIM_SetCompare4(TIM3, capture + CCR4_Val);
}
}
int main(void)
{
SystemInit();
GPIO_Configuration();
TIM_Configuration(); /* 初始化TIMx定时器 */
NVIC_Configuration();
LCD_Init(); /* LCD初始化 */
Welcome(); /* 显示主界面 */
LED1(1);LED2(1);LED3(1);LED4(1);
while(1)
{
/* 本例程,主循环体不做事情,全部在中断函数中让LED闪烁,可根据需要自行加功能代码*/
}
}
例3:输出PWM波
运行程序后PWM输出频率10kHz,起始占空比50%
void Init_TIMER(void)
{
TIM_TimeBaseInitTypeDef TIM_BaseInitStructure; //定义一个定时器结构体变量
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器4,重要!!
TIM_DeInit(TIM4); //将IM2定时器初始化位复位值
TIM_InternalClockConfig(TIM4); //配置 TIM4 内部时
TIM_BaseInitStructure.TIM_Period = 7200-1; //设置自动重载寄存器值为最大值 0~65535之间 7200/72000000=1/10000s=0.1ms即10KHz
//TIM_Period(TIM1_ARR)=7200,计数器向上计数到7200后产生更新事件,
//计数值归零 也就是 1ms产生更新事件一次
TIM_BaseInitStructure.TIM_Prescaler = 0; //自定义预分频系数为0,即定时器的时钟频率为72M提供给定时器的时钟 0~65535之间
//设置预分频器分频系数0
TIM_BaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割为0
TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
//TIM向上计数模式 从0开始向上计数,计数到1000后产生更新事件
TIM_TimeBaseInit(TIM4, &TIM_BaseInitStructure); //根据指定参数初始化TIM时间基数寄存器
TIM_ARRPreloadConfig(TIM4, ENABLE); //使能TIMx在 ARR 上的预装载寄存器
TIM_Cmd(TIM4, ENABLE); //使能TIM4
}
void Init_PWM(uint16_t Dutyfactor)
{
TIM_OCInitTypeDef TIM_OCInitStructure; //定义一个通道输出结构
TIM_OCStructInit(&TIM_OCInitStructure); //设置缺省值
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM 模式 1 输出
TIM_OCInitStructure.TIM_Pulse = Dutyfactor; //设置占空比,占空比=(CCRx/ARR)*100%或(TIM_Pulse/TIM_Period)*100%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//TIM 输出比较极性高
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出状态 需要PWM输出才需要这行代码
TIM_OC3Init(TIM4, &TIM_OCInitStructure); //根据参数初始化PWM寄存器 通道3(PB8)
TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable);//使能 TIMx在 CCR3 上的预装载寄存器
TIM_CtrlPWMOutputs(TIM4,ENABLE); //设置TIM4 的PWM 输出为使能
}
void PWM_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义一个GPIO结构体变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);
//使能各个端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8| GPIO_Pin_9; //PB8和PB9引脚,PB6、PB7、PB8和PB9分别为TIM4对应的CH1、CH2、CH3和CH4四个通道的PWM输出引脚,这里使用PB8和PB9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用输出推挽
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //配置端口速度为50M
GPIO_Init(GPIOB, &GPIO_InitStructure); //将端口GPIOD进行初始化配置
}
int main(void)
{
uint16_t Pulse=7200*0.5; //占空比为50% 周期7200(1ms)
SystemInit();
PWM_GPIO_Init(); //PWM输出口PB8,初始化
Init_TIMER(); //定时器4初始化
Init_PWM(Pulse); //PWM的通道3初始化设置
GPIO_Configuration();
TIM2_Cap_Init(0xffff,72-1); /*以1MHz的频率计数,初始化TIM2定时器 */
LCD_Init(); /* LCD初始化 */
Welcome(); /* 显示主界面 */
LED1(1);LED2(1);LED3(1);LED4(1);
while(1)
{
if(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_11)==0) //KEY1按下
{
Pulse+=100; //占空比加100
if(Pulse>=7200-1) Pulse=1;
TIM_SetCompare3(TIM4,Pulse); //写入定时器4的通道3的占空比值
}
if(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_12)==0) //KEY2按下
{
Pulse-=100; //占空比减100
if((Pulse<1)||(Pulse>7200)) Pulse=7200-1;
TIM_SetCompare3(TIM4,Pulse); //写入定时器4的通道3的占空比值
}
Delay_ms(100);
LCD_ShowNum(80,190,Pulse,8,16); /*显示总的脉冲个数*/
LCD_ShowNum(80,230,Pulse*100/7200,8,16); /*显示总的脉冲个数*/
}
}
例4:按键时长判断
利用定时计数器TIM3定时 10ms,每当 10ms 中断一次,在中断服务程序中判断按键,当按键按下超过 0.5 秒小于 1 秒时称为短按,按下超过 3 秒时为长按。
试用 C 语言写出定时器 TIM3定时 10ms 的初始化函数:
(1)当短按奇数次按键时,让 LED 发光,短按偶数按键时,让 LED 熄灭;
(2)长按偶数次按键时让蜂鸣器发声报警,长按奇数次按键时停止发声。
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_SetVecorTable(NVIC_VecTab_FLASH,0x0000);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/*---------初始化状态LED OFF------------*/
LED1(1);
}
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_TimeBaseStructure.TIM_Period=10*10-1;
TIM_TimeBaseStructure.TIM_Prescaler=SystemCoreClock/10000-1;
TIM_TimeBaseStructure.TIM_ClockDivision=0;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM3,ENABLE);
}
#define ShortKeyConst 50
#define LongKeyConst 300
u32 TP1=0, TP2=0, Times;
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11) == 0) Times++;
else{
if(Times >= LongKeyConst)
{
TP1++;
if(TP1&1 == 1) GPIO_SetBits(GPIOC,GPIO_Pin_0);
else GPIO_ResetBits(GPIOC,GPIO_Pin_4);
}
else if((Times >= ShortKeyConst) && (Times <= ShortKeyConst*2))
{
TP2++;
if(TP2&1 == 1) GPIO_SetBits(GPIOD,GPIO_Pin_2);
else GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
Times = 0;
}
}
}
int main(void)
{
SystemInit();
GPIO_Configuration();
TIM_Configuration();
NVIC_Configuration();
LCD_Init();
Welcome();
LED1(1);LED2(1);LED(3);LED(4);
while(1)
{
}
}
模拟输入输出系统设计
例1:ADC应用
对于 STM32F10x 微控制器,使用片上 ADC 通道 3(PA3 作为 ADCIN3)作为电位器位置检测的一个实例,如图 7.41 所示。当旋转电位器 VR1 时,ADCIN3 随之电压发生变化,如果电位代表位置,假设 0V表示位置 0 米,3.3V 表示 100 米,当电位器从最低端向最高端旋转时,电位从 0 到 3.3V 变化,也即位置从 0 到 100 米线性变化。试回答:
(1)写出对片上 DAC 的初始化程序片段(含引脚配置及 DAC 初始化)。
(2)写出采集电位并进行标度变换的程序。
void ADC_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|RCC_APB2Periph_ADC1,ENABLE);/*PA3 为 ADCIN3*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*管脚频率50MHz*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; /*模拟输入模式*/
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 初始化ADC:独立模式、多通道扫描、连续转换、软件触发、ADC数据右对齐 */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; /*独立工作模式*/
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通道数为1个通道(ADCIN3)*/
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE); /*使能ADC1*/
ADC_ResetCalibration(ADC1); /*使能ADC1复位校准寄存器*/
while(ADC_GetResetCalibrationStatus(ADC1)); /*等待复位校准寄存器接收*/
ADC_StartCalibration(ADC1); /*启动ADC1校准*/
while(ADC_GetCalibrationStatus(ADC1)); /*等待ADC1校准结束*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE); /*启动软件转换*/
}
int Read_ADC1_MultiChannel(u8 channNo)
{
u16 ADC_data;
ADC_RegularChannelConfig(ADC1, channNo, 1, ADC_SampleTime_239Cycles5 );/* 设置指定channNo通道及采样率*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE); /*使能ADC1 */
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); /*等待AD转换结束*/
ADC_data=ADC_GetConversionValue(ADC1); /*取AD转换结果*/
ADC_SoftwareStartConvCmd(ADC1, DISABLE); /*关闭ADC1*/
return(ADC_data); /*返回转换结果*/
}
int main()
{
int value = 0;
int voltage = 0;
int dis = 0;
ADC_Configuration ();
while(1)
{
value = Read_ADC1_MutiChannel(ADC_Channel_3);
voltage = (3300*value)/4095; // 标度转换后的电压值,单位mv
dis = (100*value)/4095; // 标度转换后的距离
}
}
例2:ADC_DAC应用
试设计一个模拟输入输出系统,采用 STM32F10x 微控制器,采用 3.3V 供电,内置 12 位 ADC,某压力传感器输出 0-100mV 对于 0-10Mpa,压力超过 8.5Mpa 时,输出报警信号,让蜂鸣器发声,低于 8Mpa时解除报警。并将得到的压力用 4-20mA 电流输出到外部。写出相关程序片段。
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_ResetBit(GPIOC,GPIO_Pin_0); // 初始化蜂鸣器不响
}
void ADC_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|RCC_APB2Periph_ADC1,ENABLE);/*PA1 为 ADCIN1*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*管脚频率50MHz*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; /*模拟输入模式*/
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 初始化ADC:独立模式、多通道扫描、连续转换、软件触发、ADC数据右对齐 */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; /*独立工作模式*/
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通道数为1个通道(ADCIN1)*/
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE); /*使能ADC1*/
ADC_ResetCalibration(ADC1); /*使能ADC1复位校准寄存器*/
while(ADC_GetResetCalibrationStatus(ADC1)); /*等待复位校准寄存器接收*/
ADC_StartCalibration(ADC1); /*启动ADC1校准*/
while(ADC_GetCalibrationStatus(ADC1)); /*等待ADC1校准结束*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE); /*启动软件转换*/
}
void DAC_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE ); //使能PORTA通道时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽(模拟)输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
DAC_DeInit();
DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能 DAC_Trigger_T3_TRGO 定时器为触发源
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化DAC通道1
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1
DAC_SetChannel1Data(DAC_Align_12b_R, 0x0); //12位右对齐数据格式设置DAC初始值,输出0
}
int Read_ADC1_MultiChannel(u8 channNo)
{
u16 ADC_data;
ADC_RegularChannelConfig(ADC1, channNo, 1, ADC_SampleTime_239Cycles5 );/* 设置指定channNo通道及采样率*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE); /*使能ADC1 */
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); /*等待AD转换结束*/
ADC_data=ADC_GetConversionValue(ADC1); /*取AD转换结果*/
ADC_SoftwareStartConvCmd(ADC1, DISABLE); /*关闭ADC1*/
return(ADC_data); /*返回转换结果*/
}
int main()
{
int high = 4095 * 8.5 / 10;
int low = 4095 * 8.0 / 10;
int Din
SystemInit();
GPIO_Configuration();
ADC_Configuration();
DAC_Configuration();
while(1)
{
Din = Read_ADC1_MultiChannel(ADC_Channel_1);
if(Din > high) GPIO_SetBit(GPIOC, GPIO_Pin_0); // 报警
else if(Din < low) GPIO_ReSetbits(GPIOC, GPIO_Pin_0); // 解除报警
Dout = 496 + (1986 * Din) / 4095;
DAC_SetChannel1Data(DAC_Align_12b_R, Dout); // 输出电流
}
}
例3:ADC_DMA应用
void GPIO_Configuration()
{ // 将用到的引脚配置为模拟输入模式
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*管脚频率50MHz*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; /*模拟输入模式*/
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void DMA_Congiguration(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA1时钟
DMA_DeInit(DMA1_Channel1); //指定DMA通道
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC_DR_Address;//设置DMA外设地址ADC_DR_Adress
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; //设置DMA内存地址,ADC转换结果直接放入该地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设为设置为数据传输的来源
DMA_InitStructure.DMA_BufferSize = SampleNum*ChannelNum; //DMA缓冲区设置
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//DMA不允许地址递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA通道
}
void ADC_Configuration(void)
{
DMA_Congiguration(); // ADC的DMA初始化
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1时钟
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //使用独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //扫描模式允许,多通道必须使能
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连接转换模式,无需外接触发器
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不用外部触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //使用数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = ChannelNum; // ChannelNum个通道转换通道
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_55Cycles5); //通道3(电位器)采样周期55.5个时钟周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 2, ADC_SampleTime_55Cycles5); //通道6(PT100)采样周期55.5个时钟周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 3, ADC_SampleTime_55Cycles5); //通道7(电流电压)采样周期55.5个时钟周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 4, ADC_SampleTime_55Cycles5); //通道16(内部温度)采样周期55.5个时钟周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 5, ADC_SampleTime_55Cycles5); //通道17(基准电压)采样周期55.5个时钟周期
ADC_DMACmd(ADC1, ENABLE); //使能ADC的DMA
ADC_Cmd(ADC1, ENABLE); //使能ADC1
ADC_TempSensorVrefintCmd(ENABLE); /*使能温度传感器和内部参考电压通道*/
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //开始转换
}
int ReadADCAverageValue(uint16_t Channel) //求平均值
{
u8 i;
u32 sum = 0;
for(i=0; i<SampleNum; i++)
{
sum+=ADC_ConvertedValue[i][Channel];
}
return (sum/SampleNum);
}
int main()
{
SystemInit();
GPIO_Configuration();
ADC_Configuration();
while(1)
{
int value0 = ReadADCAverageValue(0);
int value1 = ReadADCAverageValue(1);
int value2 = ReadADCAverageValue(2);
int value3 = ReadADCAverageValue(3);
int value4 = ReadADCAverageValue(4);
// ......
}
}
例4:DAC输出频率为f的正弦波
int index = 0;
const uint16_t Sine12bit[32] = {2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4096, 4056,
3939, 3750, 3459, 3185, 2831, 2447, 2047, 1647, 1263, 909,
599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_SetVecorTable(NVIC_VecTab_FLASH,0x0000);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM_Configuration(uint16_t f)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 ,ENABLE);
TIM_DeInit(TIM3);
TIM_TimeBaseStructure.TIM_Period = SystemCoreClock/1/32/f-1;//一个周期32个点,两间隔离时间的倒数即频率,改变这个值能改变正弦波的频率 反比例变化
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; //这个值要为零 否则无输出
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //这个值要为零 否则无输出
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM3, ENABLE); //使能TIM3
}
void DAC_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE ); //使能PORTA通道时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽(模拟)输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
DAC_DeInit();
DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化DAC通道1
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1
DAC_SetChannel1Data(DAC_Align_12b_R, 0x0); //12位右对齐数据格式设置DAC初始值,输出0
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) /*判断是否是更新中断*/
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); /*清除中断标志*/
DAC_SetChannel1Data(DAC_Align_12b_R, uint16_t Sine12bit[index++]);
if(index >= 32) index = 0;
}
}
int main()
{
NVIC_Configuration();
TIM_Configuration(f);
DAC_Configuration();
// ......
}
例5:DAC_DMA输出乐曲
uint32_t DAC_DHR12R2_Address = 0x40007414; //0x4000 7400 - 0x4000 77FF为DAC地址范围,其中0x40007414为DAC2右对齐数据保持寄存器
const uint16_t Sine12bit[32] = { /*32正弦波点*/
2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056,
3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909,
599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};
uint32_t DAC2Sine12bit[32];
const uint16_t Redfrebit[]={......} //存放音乐的频率
void TIM_Configuration(uint16_t f)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 ,ENABLE);
TIM_DeInit(TIM3);
TIM_TimeBaseStructure.TIM_Period = SystemCoreClock/1/32/f-1;//一个周期32个点,两间隔离时间的倒数即频率,改变这个值能改变正弦波的频率 反比例变化
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; //这个值要为零 否则无输出
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //这个值要为零 否则无输出
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update); //使用更新事件作为触发输出
TIM_Cmd(TIM3, ENABLE); //使能TIM3
}
void DAC_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC ,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
/*-----------DAC端口配置 复用输出模式-------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //PA5:DAC2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA ,&GPIO_InitStructure);
DAC_DeInit(); //还原到初始状态
/* DAC 通道2配置 */
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T3_TRGO; //选择定时器3作外部触发源
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //自定义波形产生
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; //失能输出缓冲
DAC_Init(DAC_Channel_2, &DAC_InitStructure); //DAC初始化
DAC_Cmd(DAC_Channel_2, ENABLE); //使能DAC
DAC_SoftwareTriggerCmd(DAC_Channel_2, ENABLE); //通道2由软件触发
}
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2 ,ENABLE); //打开DMA2时钟
DMA_DeInit(DMA2_Channel4); //将DMA通道4 的寄存器设为默认值
DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12R2_Address; //DAC2 12位右对齐数据寄存器地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&DAC2Sine12bit; //待送入DAC2的数字量
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //外设作为数据传输的来源
DMA_InitStructure.DMA_BufferSize = 32; //DMA缓存大小,32个数据(一个周期的正弦波点数)
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设寄存器地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设为16位(12位DAC)
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存数据宽度采用16位模式,对应DAC12位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循环缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设置DMA通道优先级为高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //不设置为内存到内存传输
DMA_Init(DMA2_Channel4, &DMA_InitStructure);
DMA_Cmd(DMA2_Channel4, ENABLE);
/*使能DAC通道2:PA.5被自动连接到DAC的转换器*/
DAC_Cmd(DAC_Channel_2, ENABLE);
DAC_DMACmd(DAC_Channel_2, ENABLE); //使能DAC通道2的DMA
}
int main()
{
SystemInit();
DAC_Configuration();
DMA_Configuration();
for (int Idx = 0; Idx < 32; Idx++)
{
DAC2Sine12bit[Idx] = (Sine12bit[Idx] << 16) + (Sine12bit[Idx]); //将正弦波离散点装入指定DAC2Sine12bit[]中(DMA指定的外设地址)
}
while(1)
{
if (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11)==0) KEY=1; // 按键1播放
else if (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_12)==0) KEY=2; // 按键2停止
switch (KEY)
{
case 1:
for (i=0;i<68;i++)
{
if (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_12)==0)
{
KEY=2;
TIM_Cmd(TIM3, DISABLE);
break;
}
TIM_Configuration(Redfrebit[i]); //TIM2赋值改变频率,发不同音调
Delay_ms(300);
}
break;
case 2:
TIM_Cmd(TIM3, DISABLE); //不使能定时器(不让DAC输出)
Delay_ms(300);
break;
}
}
}
互连通信接口设计
例1:USART初始化程序
#define U1Baud 115200
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
PUTCHAR_PROTOTYPE
{
USART_SendData(USART1, (uint8_t) ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
return ch;
} // 定义之后,可以使用printf
int flag = 0;
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组2
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //USART1接收中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //次占优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //USART2接收中断
NVIC_Init(&NVIC_InitStructure);
}
void USART_Configuration(uint32_t UART1_Baud)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD
|RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO, ENABLE);
/*USART1端口配置PA9 TX 复用推挽输出 PA10 RX 浮空输入模式*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*--------------USART1 配置-------------------*/
USART_InitStructure.USART_BaudRate = UART1_Baud;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}
void USART1_SendString(uint8_t *ch)
{
while(*ch!=0)
{
USART_SendData(USART1, *ch);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
ch++;
}
}
void USART1_IRQHandler(void)
{
char res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
USART_ClearFlag(USART1, USART_IT_RXNE);
res =USART_ReceiveData(USART1); // 读取接收到的数据USART1->DR
USART1_SendString("\r\n 接收到的字符是");
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
USART_SendData(USART1, res);
flag = 1;
}
}
int main()
{
SystemInit();
NVIC_Configuration();
USART_Configuration(U1Baud);
//......
}