通过超声波模块测距,然后把结果打印到串口助手上。
单片机源程序如下:
- #include "system.h"
- #include "SysTick.h"
- #include "led.h"
- #include "usart.h"
- //位带操作,实现51类似的GPIO控制功能
- //具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
- //IO口操作宏定义
- #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
- #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
- #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
- //IO口地址映射
- #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
- #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
- #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
- #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
- #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
- #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
- #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C
- #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
- #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
- #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
- #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
- #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
- #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
- #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
-
- //IO口操作,只对单一的IO口!
- //确保n的值小于16!
- #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
- #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
- #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
- #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
- #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
- #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
- #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
- #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
- #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
- #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
- #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
- #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
- #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
- #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
- #define RX PFin(3)
- #define TX PFout(4)
- /*通用延时函数*/
- #define TIME_MS 12000 //@72M
- #define TIME_US 10 //@72M
- /********声明*********/
- void StartModule(void);//启动模块
- void Timer_Count(void);//开关定时器
- void Conut(void);//计算距离
- void dispaly(void);//打印函数
- void clear(void);//清零函数
- /*长延时函数*/
- void Delay_ms(u16 n)
- {
- u16 i,j;
-
- for(i=n;i>0;i--)
- for(j=TIME_MS;j>0;j--);
- }
- /*短延时函数*/
- void Delay_us(u16 n)
- {
- u16 i,j;
-
- for(i=n;i>0;i--)
- for(j=TIME_US;j>0;j--);
- }
- unsigned int time=0;
- unsigned long S=0;
- unsigned int flag =0;
- unsigned int num;
- unsigned int average;
- unsigned int sum;
- /* 配置定时器2 */
- void TIM2_Init(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE );
- TIM_DeInit(TIM2); //缺省复位TIM2定时器
- TIM_TimeBaseStructure.TIM_Period = 65535; //周期65536 自动重装寄存器 65356us
- TIM_TimeBaseStructure.TIM_Prescaler = 71; //分频值71+1 预分频器
- TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //采样分割(滤波,外部才要,因为有很多毛刺)
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数模式:向上计数
- TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);
-
- TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除TIM2溢出中断标志
- TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //TIM2溢出中断允许
-
- // TIM_Cmd(TIM2, ENABLE); //TIM2使能
- /* 中断优先级分组配置 */
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
-
- /* 设置中断嵌套控制器 */
- NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //设置TIM2中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//主优先级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //从优先级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断通道使能
- NVIC_Init(&NVIC_InitStructure);
-
- TIM_Cmd(TIM2, DISABLE);
- }
- /*GPIO初始化函数*/
- void GPIOF_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;//定义结构体变量
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);//使能GPIOF时钟
-
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;//选择你要设置的IO口
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //设置
-
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;//选择你要设置的IO口
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//设置传输速率
-
- GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化GPIO
-
- }
- /*******************************************************************************
- * 函 数 名 : main
- * 函数功能 : 主函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- int main()
- {
- SysTick_Init(72);
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
- USART1_Init(9600);
- GPIOF_Init();
- TIM2_Init();
- while(1)
- {
- while(num<5) //每五次算平均数
- {
- RX = 1;
- StartModule(); //启动模块
- Timer_Count(); //开关定时器
- Conut(); //计算距离
- num++;
- sum+=S; //总数
- }
- average=sum/num; //平均数
- dispaly(); //打印函数
- clear(); //清零函数
- }
- }
- void StartModule(void) //启动模块
- {
- TX=1;
- Delay_us(20);
- TX=0;
- }
- void Timer_Count(void) //开启关闭定时器模块
- {
- while(RX==0);
- TIM_Cmd(TIM2, ENABLE); //TIM2使能
- while(RX==1);
- TIM_Cmd(TIM2, DISABLE); //TIM2使能
- }
- /********************************************************/
- void Conut(void) //超声波距离计算函数
- {
- time = TIM2->CNT; //读计数器值
- TIM2->CNT = 0; //清除计数器
- S=(time*1.7)/10; //算出来是MM
- if(S>=10) //校准
- S=S-10;
- }
- /*******************************************************************************
- * 函 数 名 : TIM2_IRQHandler
- * 函数功能 : TIM2中断函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void TIM2_IRQHandler(void)
- {
- if(TIM_GetITStatus(TIM2,TIM_IT_Update))
- {
- RX=0;
- flag=1;//超出量程标志
- }
- TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
- }
- /********打印函数*******/
- void dispaly(void)
- {
- if(average>=4000||flag==1)
- printf("超出量程\n");
- else
- printf("测距:%dMM\r\n",average);
- }
- /********清零函数*******/
- void clear(void)
- {
- flag=0;
- num=0;
- sum=0;
- average=0;
- }
复制代码
所有资料51hei提供下载:
超声波测距-printf重定向.7z
(182.84 KB, 下载次数: 47)
|