• 串口控制舵机转动


    任务要求

    1. 使用串口通信,电脑串口助手发送给单片机十六进制数据,对应舵机转角0~最大角度
    2. 发送数据范围0~180

     

    思路

    使用查询模式:使用的是disable串口中断
    '0’指是是ASCII字符0,不是十六进制

    1/9 1/3000
    0 1500
    45 3000
    a度数 x波
    a = (x-0.5)90
    x=a/90.0+0.5
    t = x
    3000
    1/3000
    1/9

    0 1500 0.5
    18 2100 0.7
    27 2400 0.8
    30.06 2502 0.834 1002
    36 2700 0.9
    45 3000 1 4.5=(1-0.5)*9
    63 3600 1.2 6.3=(1.2-0.5)*9 倒着算
    72 3900 1.3
    81 4200 1.4
    90 4500 1.5 9.0=(1.5-0.5)*9
    108 5100 1.7
    126 5700 1.9
    135 6000 2
    162 6900 2.3
    180 7500 2.5

    利用数据计算出公式,就可以实现无论输入任何角度,舵机都能转出对应的角度

    需要usart.h和usart.c串口通信
     

    完成代码:

    main.c

    int main (void){//主程序
    	vu16 t;
    	
    	delay_ms(500); //上电时等待其他器件就绪
    	RCC_Configuration(); //系统时钟初始化 
    	RELAY_Init();//继电器初始化
        USART1_Init(115200);
    	I2C_Configuration();//I2C初始化
    
    
    
    	TIM3_PWM_Init(59999,23); //设置频率为50Hz,公式为:溢出时间Tout(单位秒)=(arr+1)(psc+1)/Tclk	 20MS = (59999+1)*(23+1)/72000000
                              //Tclk为通用定时器的时钟,如果APB1没有分频,则就为系统时钟,72MHZ
                              //PWM时钟频率=72000000/(59999+1)*(23+1) = 50HZ (20ms),设置自动装载值60000,预分频系数24
    
    
    
    	while(1){
    
    		//查询方式接收
    		if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET){  //查询串口待处理标志位
    			a =USART_ReceiveData(USART1);//读取接收到的数据
    			//将角度转换为占空比
    
    			  t=(a/90.0+0.5)*3000.0;
    
    			  TIM_SetCompare3(TIM3,t);			
    
    				printf("%d ",a); 
    
    
    
    
    
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

     

    追加任务

    while(1)里不能写东西

    思路

    使用定时器中断
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    需要tim.c和tim.h采用定时器中断while(1)中就不需要写入程序
     

    完成代码

    main.c

    
    int main (void){//主程序
    	vu16 a;
    	vu16 t;
    
    	delay_ms(500); //上电时等待其他器件就绪
    	RCC_Configuration(); //系统时钟初始化 
    	RELAY_Init();//继电器初始化
        USART1_Init(115200);
    	I2C_Configuration();//I2C初始化
    	OLED0561_Init(); //OLED初始化
    	OLED_DISPLAY_8x16_BUFFER(0,"   YoungTalk    "); //显示字符串
    	OLED_DISPLAY_8x16_BUFFER(3,"   SG90 TEST2   "); //显示字符串
    
    	TOUCH_KEY_Init();//按键初始化
    	TIM3_PWM_Init(59999,23); //设置频率为50Hz,公式为:溢出时间Tout(单位秒)=(arr+1)(psc+1)/Tclk	 20MS = (59999+1)*(23+1)/72000000
                              //Tclk为通用定时器的时钟,如果APB1没有分频,则就为系统时钟,72MHZ
                              //PWM时钟频率=72000000/(59999+1)*(23+1) = 50HZ (20ms),设置自动装载值60000,预分频系数24
    	TIM3_Init(59999,23);//定时器初始化,定时1秒(9999,7199)
    	while(1){
         }
         }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

     

    tim.c

    void TIM3_IRQHandler(void)TIM3中断处理函数
    在这个函数体内写入串口控制舵机的程序即可

    #include "tim.h"
    
    //定时器时间计算公式Tout = ((重装载值+1)*(预分频系数+1))/时钟频率;
    //例如:1秒定时,重装载值=9999,预分频系数=7199
    
    void TIM3_Init(u16 arr,u16 psc){  //TIM3 初始化 arr重装载值 psc预分频系数
        TIM_TimeBaseInitTypeDef     TIM_TimeBaseInitStrue;
        
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM3
        TIM3_NVIC_Init (); //开启TIM3中断向量
    	      
        TIM_TimeBaseInitStrue.TIM_Period=arr; //设置自动重装载值
        TIM_TimeBaseInitStrue.TIM_Prescaler=psc; //预分频系数
        TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up; //计数器向上溢出
        TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1; //时钟的分频因子,起到了一点点的延时作用,一般设为TIM_CKD_DIV1
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStrue); //TIM3初始化设置
        TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//使能TIM3中断    
        TIM_Cmd(TIM3,ENABLE); //使能TIM3
    }
    
    void TIM3_NVIC_Init (void){ //开启TIM3中断向量
    	NVIC_InitTypeDef NVIC_InitStructure;
    	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;	
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x3;	//设置抢占和子优先级
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x3;
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_Init(&NVIC_InitStructure);
    }
    
    void TIM3_IRQHandler(void){ //TIM3中断处理函数
     u16 a;
     u16 t;  
        if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){	//判断是否是TIM3中断
            TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
    
            //此处写入用户自己的处理程序
    //		GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1-GPIO_ReadOutputDataBit(LEDPORT,LED1))); //取反LED1
    	//查询方式接收
    		if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET){  //查询串口待处理标志位
    			a =USART_ReceiveData(USART1);//读取接收到的数据
    			//将角度转换为占空比
    //			i=a/90.0;
    //			 x= a/90.0+0.5;
    			  t=(a/90.0+0.5)*3000.0;
    
    			  TIM_SetCompare3(TIM3,t);			
    
    				printf("%d ",a); 
        }
    }
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
  • 相关阅读:
    SQLite导出数据库至sql文件
    Java项目有可能做到所有的代码逻辑均可热部署吗?
    科研 | 研究成果该如何署名?
    【元宇宙欧米说】We Are:Gif格式的NFT有何特色
    (Applied Intelligence-2022)TransGait: 基于多模态的步态识别与集合Transformer
    java面向对象的内存分析
    全连接神经网络学习MNIST实现手写数字识别
    傅里叶级数@正弦级数和余弦级数@奇偶延拓和周期延拓
    JVM Heap Memory
    delphi中Message消息的使用方法
  • 原文地址:https://blog.csdn.net/Ll_R_lL/article/details/125559811