实验例子-代码

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; //1000msTIM_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; //500msTIM_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; //200msTIM_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之间//设置预分频器分频系数0TIM_BaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割为0TIM_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和PB9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       //复用输出推挽GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //配置端口速度为50MGPIO_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;                                    //占空比加100if(Pulse>=7200-1) Pulse=1;TIM_SetCompare3(TIM4,Pulse);                   //写入定时器4的通道3的占空比值}if(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_12)==0)   //KEY2按下{Pulse-=100;                                     //占空比减100if((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 300u32 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=1DAC_Init(DAC_Channel_1,&DAC_InitType);  //初始化DAC通道1DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC1DAC_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 DinSystemInit();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_AdressDMA_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的DMAADC_Cmd(ADC1, ENABLE); //使能ADC1ADC_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=1DAC_Init(DAC_Channel_1,&DAC_InitType);  //初始化DAC通道1DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC1DAC_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:DAC2GPIO_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);                                //使能DACDAC_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);              //中断分组2NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;           //USART1接收中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0NVIC_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->DRUSART1_SendString("\r\n 接收到的字符是");while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));USART_SendData(USART1, res);flag = 1;}
}int main()
{SystemInit();NVIC_Configuration();USART_Configuration(U1Baud);//......
}

嵌入式应用系统设计实例

【嵌入式原理与应用】南航嵌入式——实验例程相关推荐

  1. 51单片机学习笔记——第2天:简易门铃设计(普中51中级实验例程)

    文中绝大数代码来自普51开发板实验例程 门铃这个实验实际上就是按键和蜂鸣器的组合实验,没啥难度,唯一的用处就是为下一个实验(音乐播放器)做铺垫. 文章目录 门铃实现原理 扩展,调节"叮咚&q ...

  2. 【嵌入式实验】南航嵌入式实验报告——定时器TIMx实验

    嵌入式系统原理与应用实验报告-定时器TIMx实验 文章目录 嵌入式系统原理与应用实验报告-定时器TIMx实验 一.实验目的 1.1 TIMx的更新方式定时实验 1.2 基于TIMx的比较方式定时 1. ...

  3. 计算机四级嵌入式原理

    计算机四级嵌入式原理 第一部分--讲义 第二部分--历年真题 全国计算机等级考试四级嵌入式系统开发真题库第1套 第1套参考答案 全国计算机等级考试四级嵌入式系统开发真题库第2套 第2套参考答案 全国计 ...

  4. 利用外部中断实现清零_大工13春《嵌入式原理与开发》辅导资料十三

    大工13春<嵌入式原理与开发>辅导资料十三 2013-08-29 07:08:34 905 有学员问关于大工13春<嵌入式原理与开发>辅导资料十三的题目的参考答案和解析,具体如 ...

  5. 嵌入式系统的组成、嵌入式处理器分类总结、ARM处理器系列总结、ARM Cortex-M3体系结构总结!

    一.嵌入式系统的组成 嵌入式系统的组成主要由:嵌入式硬件系统.嵌入式软件系统. (1)嵌入式硬件系统主要包括:嵌入式处理器.存储器.模拟电路.电源.接口控制器.接插件等 1)嵌入式处理器:是嵌入式系统 ...

  6. 学习嵌入式的书籍推荐,嵌入式编程入门教程学习大纲

    嵌入式系统是当前热门.具发展前景的IT应用领域之一,很多数字包括手机.电子字典.可视电话.数字相机.数字摄像机.机顶盒.智能玩具医疗仪器和航空航天设备等都是典型的嵌入式系统.越来越多的人想要了解学习嵌 ...

  7. 什么是嵌入式?你眼中的嵌入式是怎么样的?怎么学嵌入式?教你五分钟看懂嵌入式。

    你眼中的嵌入式是怎么样的? 嵌入式的定义 从技术上来区分嵌入式 嵌入式硬件工程师必备技能 嵌入式驱动工程师必备技能 嵌入式软件开发工程师必备技能 嵌入式系统开发工程师必备技能 总结 嵌入式的定义 IE ...

  8. 嵌入式实时操作系统1——初识嵌入式实时操作系统

    嵌入式实时操作系统是什么 嵌入式实时操作系统是一个特殊的程序,是一个支持多任务的运行环境.嵌入式实时操作系统最大的特点就是"实时性",如果有一个任务需要执行,实时操作系统会立即执行 ...

  9. linux嵌入式开发板实训心得,嵌入式实训心得体会.docx

    嵌入式实训心得体会 嵌入式实训心得体会 篇一:嵌入式心得体会 这学期才接触嵌入式系统感觉还称不上入门,我通过学习知道了嵌入式的发展前景很大,各个领域都用到了嵌入式,学好嵌入式不愁没饭吃. 广义上讲,凡 ...

  10. 嵌入式系统开发与应用——嵌入式 Linux 调试环境搭建

    附录:UBoot常用命令手册 一. 实验目的 1.掌握VMware中设置共享文件夹的方法,为后续实验做准备: 2.熟悉 Linux TFTP 配置,为后续 Linux 底层开发做准备(后面会用 tft ...

最新文章

  1. C++知识点38——拷贝赋值运算符、析构函数、=default、阻止拷贝和赋值
  2. 深度学习(三十五)——Style Transfer(2), YOLOv3, Tiny-YOLO, One-stage vs. Two-stage
  3. python3调用adb命令_如何使用Python执行adb命令?
  4. MySQL考试复习(知识点、练习题)
  5. 反射 字段_java核心基础之反射
  6. 小程序 ---- (自定义头部导航)
  7. IIS6/IIS7无法打开IIS管理器的解决方法。
  8. 淘宝网打开很慢、特别慢的完美解决方法
  9. 生物信息分析中的reads是什么
  10. 如何用Python写一个安卓APP
  11. MySQL中DATE_FORMAT()函数的说明和简介
  12. e-a乘a的转置的秩_通用矩阵乘(GEMM)优化与卷积计算
  13. 晋南讲堂之Spring—(二) IOC和DI
  14. php 手机当扫描仪,只会用华为手机拍照就输了,打开相机的这个功能,手机秒变扫描仪...
  15. python基础学习06_if条件判断(多重判断、嵌套、三目运算)
  16. router vue 多个路径_vue-router 路由 总结
  17. 精读论文:Multi-Task Learning as Multi-Objective Optimization(附翻译)
  18. 吴恩达推荐好文:中国人工智能的崛起
  19. 工业互联网 - SIS系统
  20. 宝塔面板安装和创建网站/必看教程

热门文章

  1. JAVA毕设项目售楼系统(Vue+Mybatis+Maven+Mysql+sprnig+SpringMVC)
  2. Coolpad在Eclipse不输出LogCat日志
  3. [附源码]java+ssm计算机毕业设计红色旅游信息项目管理58lsu(源码+程序+数据库+部署)
  4. JDK1.8源码学习--lang包(StringBuffer)
  5. poj1442~优先队列oye
  6. 芯片老化验证流程_一种霍尔芯片老化测试装置及测试方法与流程
  7. LeetCode[860] 柠檬水找零 (贪心)
  8. NASM与link、golink和alink具体例子使用对比
  9. 看狂神视频学习JVM笔记
  10. 基于JavaGUI实现的外卖点餐订餐平台系统