STM32单片机使用Modbus-Rtu与PLC进行通讯控制16路PWM,频率、占空比可调(三)

本文详细介绍了Modbus RTU协议在控制PWM模块中的应用,包括接收函数、03功能码用于读取寄存器状态、06功能码用于单路寄存器控制,以及CRC校验的实现。通过这些函数,实现了对12路PWM的启停、频率和占空比的精确调节,并提供了CRC校验确保通信数据的准确性。
摘要由CSDN通过智能技术生成

一.modbus rtu程序部分

1.1modbus rtu 接收函数

/***********************************************************************modbusrtu寄存器*****************************************************************************************
*地址   01   02             03   04             05   06              07   08           09   10             11   12                                                                               
*功能   PWM1启停            PWM2启停            PWM3启停             PWM4启停           PWM5启停            PWM6启停            
-----------------------------------------------------------------------------------------------------------------------                     
*地址   13   14             15   16             17   18              19   20           21   22             23   24
*功能   PWM7启停            PWM8启停            PWM9启停             PWM10启停          PWM11启停           PWM12启停
*说明   以上均为,00:停止,01:启动
----------------------------------------------------------------------------------------------------------------------- 
*地址   25   26                     27   28                    29   30   
*功能   1-4路频率                   5-8路频率                  9-12路频率     
*说明   调整频率范围:1--1000,1代表100HZ,1000代表100KHZ
----------------------------------------------------------------------------------------------------------------------- 
*地址   31   32             33   34             35   36             37   38            39   40             41   42
*功能   PWM1占空比          PWM2占空比          PWM3占空比           PWM4占空比          PWM5占空比          PWM6占空比     
----------------------------------------------------------------------------------------------------------------------- 
*地址   43   44             45   46             47   48             49   50            51   52             53   54
        PWM7占空比          PWM8占空比          PWM9占空比           PWM10占空比         PWM11占空比         PWM12占空比
----------------------------------------------------------------------------------------------------------------------- 
*说明   以上调整占空比,范围为0-100
*******************************************************************************************************************************************************************************/

/**************************************************************************
*函数名称:void Modbus_Work(void)
*函数功能:Modbus Rtu处理函数
*输入参数:无
*返回值:无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void Modbus_Work(void)
{
  if(uart1_timeout_flag==1)  //如果检测到一帧数据
  {	
	if(uart1_rx_buf[0]==8)   //判断对方设备地址
	{					
	  if(CRC_Check(uart1_rx_buf,uart1_rx_count)==1)  //CRC校验
	  {
	   switch(uart1_rx_buf[1])
	   {
		case 0x03:                               //如果是03指令码
			Modbus_03(uart1_rx_buf,uart1_rx_count);//读取数据
			break;
			case 0x06:                               //如果是06指令码
			Modbus_06(uart1_rx_buf,uart1_rx_count);//单个写入数据
			break;
			default:
			break;				
		}
	   }
	   else
	   {
		 RS485_RE=1;
		 printf("modbus crc error\r\n");
		 delay_ms(2);
         RS485_RE=0;
       }				 
		}
    else
	{
	  printf("modbusrtu id error\r\n");
	}			
	uart1_timeout_flag=0;         //串口1超时标志位清零
	uart1_rx_timer_count_flag=0;  //串口1开始检测超时标志位清零
	uart1_rx_timer_count=0;		    //串口1接收计数清零
	uart1_rx_count=0;             //串口1接收计数清零
	}
  else;
}

1.2modbus rtu 03功能码

/**************************************************************************
*函数名称:void Modbus_03(u8 *data, u32 Length)
*函数功能:读取寄存器状态
*输入参数:data:Modbus Rtu数组,Length:数组长度
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
*例发送:08 03 00 01 00 03 54 92
*例返回:08 03 06 00 00 00 00 00 00 4B 25 
**************************************************************************/
void Modbus_03(u8 *data, u32 Length)
{	
    u8 read_addr;               //从哪个地址开始读
	u8 read_count;              //需要读取的个数
	u8 data_count;              //接下来有多少个数据需要发送
	u16 crcdata;                //crc校验值
	u8 i=0;	

	read_addr  =(data[2]<<8)+data[3]; //获取读寄存器的起始地址
	read_count =(data[4]<<8)+data[5]; //获取读取的个数	
	data_count = read_count * 2;      //需要发送的寄存器是两位,如00 02,因此计数乘2
  /* 地址(1)+功能码(1)+发送数据数(1)+读取寄存器个数(read_count)*2+CRC校验码(2)*/	
    uart1_tx_count=1+1+1+data_count+2; //计算需要发送的总数
	
	for(i=0;i<uart1_tx_count;i++)      //uart1_tx_buf发送数组清零
	{
	  uart1_tx_buf[i]=0;
	}

	uart1_tx_buf[0]=0x08;	            //赋值第0位--地址位
	uart1_tx_buf[1]=0x03;             //赋值第1位--功能位
	uart1_tx_buf[2]=data_count;       //赋值第2位--发送数据位
	
	for(i=0;i<data_count;i++)
	{
	  uart1_tx_buf[3+i]=Pwm_Status[read_addr+i];       //将PWM数组传递到需要发送的buf中
	}
	
	crcdata= CRC_16(uart1_tx_buf,uart1_tx_count);      //计算出CRC校验位
	uart1_tx_buf[uart1_tx_count-2] = crcdata >> 8;     //注意uart1_tx_buf数组倒数第二个为 
    uart1_tx_buf[uart1_tx_count-2]
	uart1_tx_buf[uart1_tx_count-1] = crcdata & 0xFF;   //注意uart1_tx_buf数组最后为 
    uart1_tx_buf[uart1_tx_count-1]
	
    UART_Send_Message(uart1_tx_buf,uart1_tx_count);    //发送数据
} 

1.3modbus rtu 06功能码

/**************************************************************************
*函数名称:void Modbus_06(u8 *data, u32 Length)
*函数功能:控制单路寄存器
*输入参数:data:Modbus Rtu数组,Length:数组长度
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
*例发送:08 06 00 02 00 01 E9 53
*例返回:08 06 00 02 00 01 E9 53
**************************************************************************/
void Modbus_06(u8 *data, u32 Length)
{
	u8 i;
	u16 write_addr;               //写入哪个地址
	u16 write_data;               //写入哪个地址
    u16 crcdata;                  //crc校验结果
	
	write_addr = (data[2]<<8)|data[3];   //需要控制的寄存器地址
	write_data = (data[4]<<8)|data[5];   //需要写入的数据	
	
	for(i=0;i<uart1_tx_count;i++)      //uart1_tx_buf发送数组清零
	{
	  uart1_tx_buf[i]=0;
	}
  
	if(write_addr>0x00&&write_addr<=0x0C)          //控制PWM开关
	{
	  Control_Pwm_Status(write_addr,write_data);
	} 
	
	else if(write_addr>0x0C&&write_addr<=0x0F)  //控制频率
	{
	  Control_Pwm_Fluency(write_addr,write_data);
	
	}
	else if(write_addr>0x0F&&write_addr<=0x1B)  //控制频率
	{
	  Control_Pwm_Duty_Ratio(write_addr,write_data);
	
	}

	uart1_tx_buf[0]=0x08;	            //赋值第0位--地址位
	uart1_tx_buf[1]=0x06;             //赋值第1位--功能位
	uart1_tx_buf[2]=write_addr>>8;    //赋值第2位--写入地址位高
	uart1_tx_buf[3]=write_addr&0xFF;  //赋值第3位--写入地址位低		
	uart1_tx_buf[4]=write_data>>8;    //赋值第4位--写入数据位高
	uart1_tx_buf[5]=write_data&0xFF;  //赋值第5位--写入数据位低		
	
  /* 地址(1)+功能码(1)+写入的地址(2)+写入的数据(2)+CRC校验码(2)*/	
    uart1_tx_count=1+1+2+2+2; //计算需要发送的总数	
	
	crcdata= CRC_16(uart1_tx_buf,uart1_tx_count);   //计算出CRC校验位
	uart1_tx_buf[uart1_tx_count-2] = crcdata >> 8;     //注意uart1_tx_buf数组倒数第二个为 
    uart1_tx_buf[uart1_tx_count-2]
	uart1_tx_buf[uart1_tx_count-1] = crcdata & 0xFF;   //注意uart1_tx_buf数组最后为 
    uart1_tx_buf[uart1_tx_count-1]
	
    UART_Send_Message(uart1_tx_buf,uart1_tx_count);    //发送数据
}

1.4modbus rtu CRC校验


/****************************************CRC校验查表方式实现****************************************************/
static const u8 TabH[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40
};

static const u8 TabL[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
0x41, 0x81, 0x80, 0x40
};


/**************************************************************************
*函数名称:u16 CRC_Check(u8 *data, u32 Length)
*函数功能:输入接收到的Modbus Rtu数据,判断是否符合CRC校验
*输入参数:data:Modbus Rtu数组,Length:数组长度
*返回值: 1:符合CRC校验,0:不符合CRC校验
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
u16 CRC_Check(u8 *data, u32 Length)
{
	//u16 crc_data;
    u8 crc_data_H = 0xFF;  //计算得出的CRC高8位,因为与计算出来的高低位是颠倒的,所以实际应该对应数组最后的值
    u8 crc_data_L = 0xFF;  //计算得出的CRC低8位,因为与计算出来的高低位是颠倒的,所以实际应该对应数组倒数第二个的值
    u16 index;
    
	u8 Len;                //需要计算的长度,即:Length-2
	u8 data_H_crc;         //实际发送过来的数组CRC高8位,即对应数组倒数第二个的值
  	u8 data_L_crc;         //实际发送过来的数组CRC低8位,即对应数组数组最后的值
	
	Len=Length-2;  
    data_H_crc=data[Length-2];	  
    data_L_crc=data[Length-1];	
	
    while( Len-- )
    {
      index = crc_data_L^* data++;
      crc_data_L =crc_data_H^TabH[index];
      crc_data_H= TabL[index];
    }
   // crc_data=crc_data_L<< 8|crc_data_H;    //保留未使用,校验的总结果
	 if((crc_data_H==data_L_crc)&&(crc_data_L==data_H_crc))    //判断校验结果
	 {
	  return 1;           //符合CRC校验返回1
	 }
	 else
	  return 0;          //否则返回0
}

/**************************************************************************
*函数名称:CRC_16(u8 *data, u32 Length)
*函数功能:输入接收到的Modbus Rtu数据,输出CRC校验的数值结果
*输入参数:data:Modbus Rtu数组,Length:数组长度
*返回值: CRC校验的数值结果
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
u16 CRC_16(u8 *data, u32 Length)
{
	u16 crc_data;
    u8 crc_data_H = 0xFF;  //计算得出的CRC高8位,因为与计算出来的高低位是颠倒的,所以实际应该对应数组最后的值
    u8 crc_data_L = 0xFF;  //计算得出的CRC低8位,因为与计算出来的高低位是颠倒的,所以实际应该对应数组倒数第二个的值
    u16 index;
    u8 Len;

	Len=Length-2;  	
    while( Len-- )
    {
      index = crc_data_L^* data++;
      crc_data_L =crc_data_H^TabH[index];
      crc_data_H= TabL[index];
    }
    crc_data=crc_data_L<< 8|crc_data_H;    //校验的总结果
	return crc_data;
}

1.5控制PWM开关函数

**************************************************************************
*函数名称:void Control_Pwm_On(u16 count)
*函数功能:控制PWM输出开关
*输入参数:count:选择第几个PWM打开
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/

void Control_Pwm_Status(u16 count,u16 data)
{
  if(data==1)
  {
    switch(count)
    {
  	  case 1:
  		  TIM2->CCER|=0x0001;  //打开第1路PWM,CCER为PWM使能寄存器
  		  break;
  		case 2:
  		  TIM2->CCER|=0x0010;  //打开第2路PWM,CCER为PWM使能寄存器	
  		  break;
  	  case 3:
  		  TIM2->CCER|=0x0100;  //打开第3路PWM,CCER为PWM使能寄存器		
  		  break;
  		case 4:
  		  TIM2->CCER|=0x1000;  //打开第4路PWM,CCER为PWM使能寄存器	
  		  break;
  	  case 5:
  		  TIM3->CCER|=0x0001;  //打开第5路PWM,CCER为PWM使能寄存器
  		  break;
  		case 6:
  		  TIM3->CCER|=0x0010;  //打开第6路PWM,CCER为PWM使能寄存器
  		  break;
  	  case 7:
  		  TIM3->CCER|=0x0100;  //打开第7路PWM,CCER为PWM使能寄存器	
  		  break;
  		case 8:
  		  TIM3->CCER|=0x1000;  //打开第8路PWM,CCER为PWM使能寄存器
  		  break;
  	  case 9:
  		  TIM4->CCER|=0x0001;  //打开第9路PWM,CCER为PWM使能寄存器
  		  break;
  		case 10:
  		  TIM4->CCER|=0x0010;  //打开第10路PWM,CCER为PWM使能寄存器	
  		  break;
  	  case 11:
  		  TIM4->CCER|=0x0100;  //打开第11路PWM,CCER为PWM使能寄存器	
  		  break;
  		case 12:
  		  TIM4->CCER|=0x1000;  //打开第12路PWM,CCER为PWM使能寄存器	
  		  break;		
  	  default:
        break;			
  	}
		
	Pwm_Status[count*2-1]=data>>8;//完成操作后赋值到寄存器数组
	Pwm_Status[count*2]=data&0xFF;//完成操作后赋值到寄存器数组
	}	
	else if(data==0)
	{
    switch(count)
  	{
  	  case 1:
  		  TIM2->CCER&=0xFFFE;  //关闭第1路PWM,CCER为PWM使能寄存器
  		  break;
  	  case 2:
  		  TIM2->CCER&=0xFFEF;  //关闭第2路PWM,CCER为PWM使能寄存器	
  		  break;
  	  case 3:
  		  TIM2->CCER&=0xFEFF;  //关闭第3路PWM,CCER为PWM使能寄存器		
  		  break;
  		case 4:
  		TIM2->CCER&=0xEFFF;  //打关闭第4路PWM,CCER为PWM使能寄存器	
  		  break;
  	  case 5:
  		TIM3->CCER&=0xFFFE;  //关闭第5路PWM,CCER为PWM使能寄存器
  		  break;
  		case 6:
  		  TIM3->CCER&=0xFFEF;  //关闭第6路PWM,CCER为PWM使能寄存器
  		  break;
  	  case 7:
  		  TIM3->CCER&=0xFEFF;  //关闭第7路PWM,CCER为PWM使能寄存器	
  		  break;
  	  case 8:
  		  TIM3->CCER&=0xEFFF;  //关闭第8路PWM,CCER为PWM使能寄存器
  		  break;
  	  case 9:
  		  TIM4->CCER&=0xFFFE;  //关闭第9路PWM,CCER为PWM使能寄存器
  		  break;
  		case 10:
  		TIM4->CCER&=0xFFEF;  //关闭第10路PWM,CCER为PWM使能寄存器	
  		  break;
  	  case 11:
  		  TIM4->CCER&=0xFEFF;  //打关闭第11路PWM,CCER为PWM使能寄存器	
  		  break;
  	  case 12:
  		  TIM4->CCER&=0xEFFF;  //关闭第12路PWM,CCER为PWM使能寄存器	
  		  break;		
  	  default:
        break;			
  	}
	Pwm_Status[count*2-1]=data>>8;//完成操作后赋值到寄存器数组
	Pwm_Status[count*2]=data&0xFF;//完成操作后赋值到寄存器数组	
	}
	else;
}

1.6控制PWM频率函数

/**************************************************************************
*函数名称:void Control_Pwm_Fluency(u16 count,u16 data)
*函数功能:控制PWM输出频率
*输入参数:count:调整第几路PWM,调整频率
*返回值: 无
*编写人:张楠  (data[2]<<8)+data[3]
*编写日期:2022.04.02
**************************************************************************/
void Control_Pwm_Fluency(u16 count,u16 data)
{
  if(count==0x0D)//调整频率后自动关闭输出,再检测之前哪路在开启状态再打开
	{
		
		TIM2_PWM_CH1_Init(data,(Pwm_Status[31]<<8)+Pwm_Status[32]);
		TIM2_PWM_CH2_Init(data,(Pwm_Status[33]<<8)+Pwm_Status[34]);
		TIM2_PWM_CH3_Init(data,(Pwm_Status[35]<<8)+Pwm_Status[36]);
		TIM2_PWM_CH4_Init(data,(Pwm_Status[37]<<8)+Pwm_Status[38]);

		if((Pwm_Status[1]<<8)+Pwm_Status[2]==1)
		{
		  TIM2->CCER|=0x0001;  //打开第1路PWM
		}
		if((Pwm_Status[3]<<8)+Pwm_Status[4]==1)
		{
		  TIM2->CCER|=0x0010;  //打开第2路PWM
		}
		if((Pwm_Status[5]<<8)+Pwm_Status[6]==1)
		{
		  TIM2->CCER|=0x0100;  //打开第3路PWM
		}
		if((Pwm_Status[7]<<8)+Pwm_Status[8]==1)
		{
		  TIM2->CCER|=0x1000;  //打开第4路PWM
		}		
	}
	else if(count==0x0E)
	{
		TIM3_PWM_CH1_Init(data,(Pwm_Status[39]<<8)+Pwm_Status[40]);
		TIM3_PWM_CH2_Init(data,(Pwm_Status[41]<<8)+Pwm_Status[42]);
		TIM3_PWM_CH3_Init(data,(Pwm_Status[43]<<8)+Pwm_Status[44]);
		TIM3_PWM_CH4_Init(data,(Pwm_Status[45]<<8)+Pwm_Status[46]);
	
		if((Pwm_Status[9]<<8)+Pwm_Status[10]==1)
		{
		  TIM3->CCER|=0x0001;  //打开第5路PWM
		}
		if((Pwm_Status[11]<<8)+Pwm_Status[12]==1)
		{
		  TIM3->CCER|=0x0010;  //打开第6路PWM
		}
		if((Pwm_Status[13]<<8)+Pwm_Status[14]==1)
		{
		  TIM3->CCER|=0x0100;  //打开第7路PWM
		}
		if((Pwm_Status[15]<<8)+Pwm_Status[16]==1)
		{
		  TIM3->CCER|=0x1000;  //打开第8路PWM
		}		
	}
	else if(count==0x0F)
	{
		TIM4_PWM_CH1_Init(data,(Pwm_Status[47]<<8)+Pwm_Status[48]);
		TIM4_PWM_CH2_Init(data,(Pwm_Status[49]<<8)+Pwm_Status[50]);
		TIM4_PWM_CH3_Init(data,(Pwm_Status[51]<<8)+Pwm_Status[52]);
		TIM4_PWM_CH4_Init(data,(Pwm_Status[53]<<8)+Pwm_Status[54]);
	
		if((Pwm_Status[17]<<8)+Pwm_Status[18]==1)
		{
		  TIM4->CCER|=0x0001;  //打开第9路PWM
		}
		if((Pwm_Status[19]<<8)+Pwm_Status[20]==1)
		{
		  TIM4->CCER|=0x0010;  //打开第10路PWM
		}
		if((Pwm_Status[21]<<8)+Pwm_Status[22]==1)
		{
		  TIM4->CCER|=0x0100;  //打开第11路PWM
		}
		if((Pwm_Status[23]<<8)+Pwm_Status[24]==1)
		{
		  TIM4->CCER|=0x1000;  //打开第12路PWM
		}	
	}	
  else;
	Pwm_Status[count*2-1]=data>>8;//完成操作后赋值到寄存器数组
	Pwm_Status[count*2]=data&0xFF;//完成操作后赋值到寄存器数组	
}

1.7控制PWM占空比函数

**************************************************************************
*函数名称:void Control_Pwm_Duty_Ratio(u16 count,u16 data)
*函数功能:控制PWM输出占空比
*输入参数:count:调整第几路PWM,调整占空比
*返回值: 无
*编写人:张楠
*编写日期:2022.04.02
**************************************************************************/
void Control_Pwm_Duty_Ratio(u16 count,u16 data)
{
  switch(count)
  {
/*********************1-4路*******************************/	
	case 16:
		TIM2_PWM_CH1_Init((Pwm_Status[25]<<8)+Pwm_Status[26],data);
		if((Pwm_Status[1]<<8)+Pwm_Status[2]==1)
		{
		  TIM2->CCER|=0x0001;  //打开第1路PWM
		}
		 break;
	  case 17:
	    TIM2_PWM_CH2_Init((Pwm_Status[25]<<8)+Pwm_Status[26],data);
		if((Pwm_Status[3]<<8)+Pwm_Status[4]==1)
		{
		 TIM2->CCER|=0x0010;  //打开第2路PWM
		}
		break;
	  case 18:
		TIM2_PWM_CH3_Init((Pwm_Status[25]<<8)+Pwm_Status[26],data);
		if((Pwm_Status[5]<<8)+Pwm_Status[6]==1)
		{
		 TIM2->CCER|=0x0100;  //打开第3路PWM
		}
		break;
	  case 19:
		TIM2_PWM_CH4_Init((Pwm_Status[25]<<8)+Pwm_Status[26],data);
		if((Pwm_Status[7]<<8)+Pwm_Status[8]==1)
		{
		  TIM2->CCER|=0x1000;  //打开第4路PWM
		}
		break;
/*********************5-8路*******************************/			
	  case 20:
		TIM3_PWM_CH1_Init((Pwm_Status[27]<<8)+Pwm_Status[28],data);
		if((Pwm_Status[9]<<8)+Pwm_Status[10]==1)
		{
		TIM3->CCER|=0x0001;  //打开第5路PWM
		}
		 break;
	  case 21:
		TIM3_PWM_CH2_Init((Pwm_Status[27]<<8)+Pwm_Status[28],data);
		if((Pwm_Status[11]<<8)+Pwm_Status[12]==1)
		{
		TIM3->CCER|=0x0010;  //打开第6路PWM
	    }
		break;
	  case 22:
		TIM3_PWM_CH3_Init((Pwm_Status[27]<<8)+Pwm_Status[28],data);
		if((Pwm_Status[13]<<8)+Pwm_Status[14]==1)
		{
		TIM3->CCER|=0x0100;  //打开第7路PWM
		}
		break;
	  case 23:
		TIM3_PWM_CH4_Init((Pwm_Status[27]<<8)+Pwm_Status[28],data);
		if((Pwm_Status[15]<<8)+Pwm_Status[16]==1)
		{
		TIM3->CCER|=0x1000;  //打开第8路PWM
		}
		break;
/*********************9-12路*******************************/				
	  case 24:
		TIM4_PWM_CH1_Init((Pwm_Status[29]<<8)+Pwm_Status[30],data);
		if((Pwm_Status[17]<<8)+Pwm_Status[18]==1)
		{
		TIM4->CCER|=0x0001;  //打开第9路PWM
	    }
		break;
	  case 25:
		TIM4_PWM_CH2_Init((Pwm_Status[29]<<8)+Pwm_Status[30],data);
		if((Pwm_Status[19]<<8)+Pwm_Status[20]==1)
		{
		TIM4->CCER|=0x0010;  //打开第10路PWM
		}
		break;
	  case 26:
		TIM4_PWM_CH3_Init((Pwm_Status[29]<<8)+Pwm_Status[30],data);
		if((Pwm_Status[21]<<8)+Pwm_Status[22]==1)
		{
		 TIM4->CCER|=0x0100;  //打开第11PWM
		}
		 break;
	  case 27:
		TIM4_PWM_CH4_Init((Pwm_Status[29]<<8)+Pwm_Status[30],data);
		if((Pwm_Status[23]<<8)+Pwm_Status[24]==1)
		{
		 TIM4->CCER|=0x1000;  //打开第12路PWM
		}
		 break;			
		default:
		 break;
	}
  Pwm_Status[count*2-1]=data>>8;//完成操作后赋值到寄存器数组
  Pwm_Status[count*2]=data&0xFF;//完成操作后赋值到寄存器数组	
}

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张楠0805

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值