MSP432P401R 速成(电赛必备)-程序员宅基地

技术标签: MSP430/432  MSP432  TI  嵌入式硬件  单片机  


废话不多说,代码看着拿

一、LED

#include "led.h"

void LED_Init(void)
{
    
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2);

    LED_RED_Off();
    LED_R_Off();
    LED_G_Off();
    LED_B_Off();
}
void LED_RED_On(void) {
     LED_RED = 1; }
void LED_RED_Off(void) {
     LED_RED = 0; }
void LED_RED_Tog(void) {
     LED_RED ^= 1; }

void LED_R_Off(void) {
     LED_R = 0;}
void LED_G_Off(void) {
     LED_G = 0;}
void LED_B_Off(void) {
     LED_B = 0; }

void LED_R_On(void) {
     LED_R = 1; }
void LED_G_On(void) {
     LED_G = 1;  }
void LED_B_On(void) {
     LED_B = 1;  }

void LED_R_Tog(void) {
     LED_R ^= 1; }
void LED_G_Tog(void) {
     LED_G ^= 1; }
void LED_B_Tog(void) {
     LED_B ^= 1; }

//白色 White
void LED_W_On(void)
{
    
    LED_R_On();
    LED_G_On();
    LED_B_On();
}
//白色 White
void LED_W_Off(void)
{
    
    LED_R_Off();
    LED_G_Off();
    LED_B_Off();
}
//白色 White
void LED_W_Tog(void)
{
    
    LED_R_Tog();
    LED_G_Tog();
    LED_B_Tog();
}
//黄色 Yellow
void LED_Y_On(void)
{
    
    LED_R_On();
    LED_G_On();
    LED_B_Off();
}
//品红 Pinkish red
void LED_P_On(void)
{
    
    LED_R_On();
    LED_G_Off();
    LED_B_On();
}
//青色 Cyan
void LED_C_On(void)
{
    
    LED_R_Off();
    LED_G_On();
    LED_B_On();
}


二、Key

#include "key.h"

//按键初始化函数
void KEY_Init(void) //IO初始化
{
    
	GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1 | GPIO_PIN4);
}
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,KEY1按下
//2,KEY2按下
//注意此函数有响应优先级,KEY1>KEY2!!
uint8_t KEY_Scan(uint8_t mode)
{
    
	uint16_t i;
	static uint8_t key_up = 1; //按键按松开标志
	if (mode)
		key_up = 1; //支持连按
	if (key_up && (KEY2 == 0 || KEY1 == 0))
	{
    
		for (i = 0; i < 5000; i++)
			; //去抖动
		key_up = 0;
		if (KEY1 == 0)
			return KEY1_PRES;
		else if (KEY2 == 0)
			return KEY2_PRES;
	}
	else if (KEY2 == 1 && KEY1 == 1)
		key_up = 1;
	return 0; // 无按键按下
}

三、key 4*4

#include "key4x4.h"
/****************************************************/
/************          接法如下          ************/
/*                                                    
 *         Rows and columns  行和列
 *
 * R4   R3   R2   R1     C1   C2   C3   C4
 * P4.0 P4.1 P4.2 P4.3   P4.4 P4.5 P4.6 P4.7
 *
 *   返回的键值 :   S1=16  S2=15  S3=14......  S16=1
*/
/*****************************************************/

//函数功能:延时
void key_delay(uint16_t t);

void KEY4x4_Init(void)
{
    
    P4DIR &= ~(BIT0 | BIT1 | BIT2 | BIT3); // P4.0~3 设为输入
    P4REN |= BIT0 | BIT1 | BIT2 | BIT3;    // P4.0~3 使能上拉/下拉电阻
    P4OUT |= BIT0 | BIT1 | BIT2 | BIT3;    // P4.0~3 上拉
    P4DIR |= BIT4 | BIT5 | BIT6 | BIT7;    // P4.4~7 设为输出
}

//按键处理函数
//返回按键值
//mode:0,不支持连续按; 1,支持连续按
uint8_t KEY4x4_Scan(bool mode)
{
    
    uint8_t i;
    static bool key_up = true; //按键按松开标志
    if (mode)
        key_up = true; //支持连按
    if ((~(P4IN | 0xf0)) && key_up)
    {
    
        key_delay(25); //去抖动
        for (i = 0; i < 4; i++)
        {
    
            key_up = false;
            P4OUT = ~(1 << (i + 4));      //+4是应为 忽略低四位
            switch (~P4IN & 0x0F) //第i+1行
            {
    
            case 0x08: //第四列
                return i + 1;
            case 0x04: //第三列
                return i + 5;
            case 0x02: //第二列
                return i + 9;
            case 0x01: //第一列
                return i + 13;
            }
        }
    }
    else if ((P4IN & 0x01) && (P4IN & 0x02) && (P4IN & 0x04) && (P4IN & 0x08))
        key_up = true;
    return 0;
}

//函数功能:延时
static void key_delay(uint16_t t)
{
    
    volatile uint16_t x;
    while (t--)
        for (x = 0; x < 1000; x++)
            ;
}

四、External_Interrupt

#include "exit.h"
#include "led.h"

int num=0,num1=0;

void Exit_Init(void) 
{
    
	//IO初始化
	GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P5, GPIO_PIN5);
	GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P6, GPIO_PIN5);
	
	//2.清除中断标志位
	GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN5);
	GPIO_clearInterruptFlag(GPIO_PORT_P6, GPIO_PIN5);
	
	//3.配置触发方式
	GPIO_interruptEdgeSelect(GPIO_PORT_P5, GPIO_PIN5,GPIO_HIGH_TO_LOW_TRANSITION);
	GPIO_interruptEdgeSelect(GPIO_PORT_P6, GPIO_PIN5,GPIO_LOW_TO_HIGH_TRANSITION);
	
	//4.开启外部中断
	GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN5);
	GPIO_enableInterrupt(GPIO_PORT_P6, GPIO_PIN5);
	
	//5.开启端口中断
	Interrupt_enableInterrupt(INT_PORT5);
	Interrupt_enableInterrupt(INT_PORT6);
	
	//6.开启总中断
	Interrupt_enableMaster();
}


void PORT5_IRQHandler(void)
{
    
	uint16_t status;
	status = GPIO_getEnabledInterruptStatus(GPIO_PORT_P5);
	GPIO_clearInterruptFlag(GPIO_PORT_P5,status);
	
	if(BITBAND_PERI(P5IN, 5)==0)
	{
    		
		******
	}

}

void PORT6_IRQHandler(void)
{
    
	uint16_t status;
	status = GPIO_getEnabledInterruptStatus(GPIO_PORT_P6);
	GPIO_clearInterruptFlag(GPIO_PORT_P6,status);
	
	if(BITBAND_PERI(P6IN, 5)==1)
	{
    		
		******
	}
}

五、蓝牙_Uart

#include "usart.h"
#include "baudrate_calculate.h"

//预编译
//if 1 使用标准C库 如果报错就使用微库
//if 0 使用微库 得去勾选魔术棒里的 Use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
    
  int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
    
  x = x;
}
#else
int fgetc(FILE *f)
{
    
  while (EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG !=
         UART_getInterruptStatus(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG))
    ;
  return UART_receiveData(EUSCI_A0_BASE);
}
#endif

int fputc(int ch, FILE *f)
{
    
  UART_transmitData(EUSCI_A0_BASE, ch & 0xFF);
  return ch;
}


void UARTA0_Init(void)
{
    
    //1.配置GPIO复用
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);

    //2.配置UART结构体
#ifdef EUSCI_A_UART_7_BIT_LEN
    //固件库v3_40_01_02
    //默认SMCLK 48MHz 比特率 115200
    const eUSCI_UART_ConfigV1 uartConfig =
        {
    
            EUSCI_A_UART_CLOCKSOURCE_SMCLK,                // SMCLK Clock Source
            26,                                            // BRDIV = 26
            0,                                             // UCxBRF = 0
            111,                                           // UCxBRS = 111
            EUSCI_A_UART_NO_PARITY,                        // No Parity
            EUSCI_A_UART_LSB_FIRST,                        // MSB First
            EUSCI_A_UART_ONE_STOP_BIT,                     // One stop bit
            EUSCI_A_UART_MODE,                             // UART mode
            EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling
            EUSCI_A_UART_8_BIT_LEN                         // 8 bit data length
        };
    eusci_calcBaudDividers((eUSCI_UART_ConfigV1 *)&uartConfig, 115200); //配置波特率
#else
    //固件库v3_21_00_05
    //默认SMCLK 48MHz 比特率 115200
    const eUSCI_UART_Config uartConfig =
        {
    
            EUSCI_A_UART_CLOCKSOURCE_SMCLK,                // SMCLK Clock Source
            26,                                            // BRDIV = 26
            0,                                             // UCxBRF = 0
            111,                                           // UCxBRS = 111
            EUSCI_A_UART_NO_PARITY,                        // No Parity
            EUSCI_A_UART_LSB_FIRST,                        // MSB First
            EUSCI_A_UART_ONE_STOP_BIT,                     // One stop bit
            EUSCI_A_UART_MODE,                             // UART mode
            EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling
        };
    eusci_calcBaudDividers((eUSCI_UART_Config *)&uartConfig, 115200); //配置波特率
#endif
    //3.初始化串口
    UART_initModule(EUSCI_A0_BASE, &uartConfig);

    //4.开启串口模块
    UART_enableModule(EUSCI_A0_BASE);
	
    //5.开启串口相关中断
    UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);

    //6.开启串口端口中断
    Interrupt_enableInterrupt(INT_EUSCIA0);

    //7.开启总中断
    Interrupt_enableMaster();
}

六、TimA0

#include "timA.h"

/**************************************         TIMA0          *******************************************/

void TimA0_Int_Init(uint16_t ccr0, uint16_t psc)
{
    
    // 1.增计数模式初始化
    Timer_A_UpModeConfig upConfig;
    upConfig.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;                                      //时钟源
    upConfig.clockSourceDivider = psc;                                                     //时钟分频 范围1-64
    upConfig.timerPeriod = ccr0;                                                           //自动重装载值(ARR)
    upConfig.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;                   //禁用 tim溢出中断
    upConfig.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE; //启用 ccr0更新中断
    upConfig.timerClear = TIMER_A_DO_CLEAR;                                                // Clear value

    // 2.初始化定时器A
    MAP_Timer_A_configureUpMode(TIMER_A0_BASE, &upConfig);

    // 3.选择模式开始计数
    MAP_Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE);

    // 4.清除比较中断标志位
    MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0);

    // 5.开启串口端口中断
    MAP_Interrupt_enableInterrupt(INT_TA0_0);
}

// 6.编写TIMA ISR
void TA0_0_IRQHandler(void)
{
    
    MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0);

    /*开始填充用户代码*/

    MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);

    /*结束填充用户代码*/
}

七、PWM

#include "pwm.h"

void TimA0_PWM_Init(uint16_t ccr0, uint16_t psc)
{
    
	    /*初始化引脚*/
    MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION);
	MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION);
//	MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN6, GPIO_PRIMARY_MODULE_FUNCTION);
	

    Timer_A_PWMConfig TimA0_PWMConfig;
    /*定时器PWM初始化*/
    TimA0_PWMConfig.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;             //时钟源
    TimA0_PWMConfig.clockSourceDivider = psc;                            //时钟分频 范围1-64
    TimA0_PWMConfig.timerPeriod = ccr0;                                  //自动重装载值(ARR)
    TimA0_PWMConfig.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1; //通道一
    TimA0_PWMConfig.compareOutputMode = TIMER_A_OUTPUTMODE_TOGGLE_SET;   //输出模式                              

    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &TimA0_PWMConfig); /* 初始化比较寄存器以产生 PWM1 */	
	
	TimA0_PWMConfig.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2; //通道2
	MAP_Timer_A_generatePWM(TIMER_A0_BASE, &TimA0_PWMConfig);
}

八、舵机SG90

#include "sg90.h"
#include "delay.h"
/*
                20ms为例
        0.5ms ------------ 0度;
        1.0ms ------------ 45度;
        1.5ms ------------ 90度;
        2.0ms ------------ 135度;
        2.5ms ------------ 180度;
*/

void SG90_angle(int a)
{
    
    int pwm=500+2000/180*a;
    MAP_Timer_A_setCompareValue(TIMER_A2_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_1, pwm);
} 


void SG90_Cal(void)
{
    
    int i=0,j=0;
    for(i=0;i<=180;i++)
    {
    
		delay_ms(65);
        SG90_angle(i);
    }
    for(j=180;j>=0;j--)
    {
    
		delay_ms(65);
        SG90_angle(j);
    }
}

九、ADC

/*********************
 *
 * 最大采集电压 3.3V
 *
 * ADC采集引脚:
 * 单路 为 P5.5
 * 双路 为 P5.5 P5.4
 * 三路 为 P5.5 P5.4 P5.3
 *
 ************************/
 
#include "adc.h"
#include "usart.h"
 
//总时间  M*N*21us
#define N 200 //采样次数
#define M 3   //采样通道个数

static uint16_t resultsBuffer[M];

void ADC_Config(void)
{
    
	/* 启用浮点运算的FPU */
    MAP_FPU_enableModule();
    MAP_FPU_enableLazyStacking();
	
    /* Initializing ADC (MCLK/1/1) */
    MAP_ADC14_enableModule();                                                                 //使能ADC14模块
    MAP_ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_4, ADC_DIVIDER_5, ADC_NOROUTE); //初始化ADC 时钟 分频  通道 2.4MHz 

#if M == 1
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5, GPIO_TERTIARY_MODULE_FUNCTION); //模拟输入
    MAP_ADC14_configureSingleSampleMode(ADC_MEM0, true);                                                    //单通道配置 多次转化true
    MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A0, false);       //使用内部电源电压参考 非差分输入false
    MAP_ADC14_enableInterrupt(ADC_INT0);                                                                    //ADC通道0的中断

#elif M == 2
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5 | GPIO_PIN4, GPIO_TERTIARY_MODULE_FUNCTION);
    MAP_ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM1, true); //多通道配置 多次转化true
    MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A0, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM1, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A1, false);
    MAP_ADC14_enableInterrupt(ADC_INT1);

#elif M == 3
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5 | GPIO_PIN4 | GPIO_PIN3, GPIO_TERTIARY_MODULE_FUNCTION); //
    MAP_ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM2, true);
    MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A0, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM1, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A1, false);
    MAP_ADC14_configureConversionMemory(ADC_MEM2, ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A2, false);
    MAP_ADC14_enableInterrupt(ADC_INT2);

#endif
    /* Enabling Interrupts */
    MAP_Interrupt_enableInterrupt(INT_ADC14); //ADC模块的中断
    MAP_Interrupt_enableMaster();

    /* Setting up the sample timer to automatically step through the sequence
     * convert.
     */
    MAP_ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION); //自动触发

    /* Triggering the start of the sample */
    MAP_ADC14_enableConversion();        //使能开始转换(触发后 自动ADC上电)
    MAP_ADC14_toggleConversionTrigger(); //开启第一次软件触发
}

void ADC14_IRQHandler(void)
{
    
    uint8_t i = 0;
    uint_fast64_t status = MAP_ADC14_getEnabledInterruptStatus();
    MAP_ADC14_clearInterruptFlag(status);
	
#if M == 1
    if (ADC_INT0 & status)
#elif M == 2
    if (ADC_INT1 & status)
#elif M == 3
    if (ADC_INT2 & status)
#endif
    {
    
        MAP_ADC14_getMultiSequenceResult(resultsBuffer);
        for (i = 0; i < M; i++)
		{
    
			float temp=resultsBuffer[i]*(3.3/16383);
            printf("ADC14_CH[%d]:%d ----- %f\r\n", i, resultsBuffer[i],temp);
		}
        printf("\r\n");
    }
}

十、OLED

#include "oled.h"
#include "oledfont.h"
#include "delay.h"

#define OLED_DATA 1
#define OLED_CMD 0

//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127

#if (TRANSFER_METHOD == HW_IIC)
//I2C_Configuration,初始化硬件IIC引脚
void I2C_Configuration(void)
{
    
  MAP_GPIO_setAsPeripheralModuleFunctionInputPin(
      IIC_GPIOX, IIC_SCL_Pin | IIC_SDA_Pin, GPIO_PRIMARY_MODULE_FUNCTION);
  const eUSCI_I2C_MasterConfig i2cConfig =
      {
    
          EUSCI_B_I2C_CLOCKSOURCE_SMCLK,   // SMCLK Clock Source
          48000000,                        // SMCLK = 48MHz
          EUSCI_B_I2C_SET_DATA_RATE_1MBPS, // Desired I2C Clock of 1MHz(实际可以更高,根据I2C协议可以3.4MHz,注意上拉电阻配置
          0,                               // No byte counter threshold
          EUSCI_B_I2C_NO_AUTO_STOP         // No Autostop
      };
  MAP_I2C_initMaster(EUSCI_BX, &i2cConfig);
  MAP_I2C_setSlaveAddress(EUSCI_BX, OLED_ADDRESS);
  MAP_I2C_setMode(EUSCI_BX, EUSCI_B_I2C_TRANSMIT_MODE);
  MAP_I2C_enableModule(EUSCI_BX);

  // MAP_I2C_clearInterruptFlag(
  // 	EUSCI_BX, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 | EUSCI_B_I2C_NAK_INTERRUPT);
  // MAP_I2C_enableInterrupt(
  // 	EUSCI_BX, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 | EUSCI_B_I2C_NAK_INTERRUPT);
  // MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
}
//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(uint8_t dat, uint8_t mode)
{
    
  if (mode)
    MAP_I2C_masterSendMultiByteStart(EUSCI_BX, 0x40);
  else
    MAP_I2C_masterSendMultiByteStart(EUSCI_BX, 0x00);
  MAP_I2C_masterSendMultiByteFinish(EUSCI_BX, dat);
}

#elif (TRANSFER_METHOD == SW_IIC)

void I2C_SW_Configuration()
{
    
  OLED_SSD1306_SCL_IO_INIT;
  OLED_SSD1306_SDA_IO_INIT;
  delay_ms(200);
}

//起始信号
void I2C_Start(void)
{
    
  OLED_SDA_Set();
  OLED_SCL_Set();
  OLED_SDA_Clr();
  OLED_SCL_Clr();
}

//结束信号
void I2C_Stop(void)
{
    
  OLED_SDA_Clr();
  OLED_SCL_Set();
  OLED_SDA_Set();
}

//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{
    
  OLED_SDA_Set();
  OLED_SCL_Set();
  OLED_SCL_Clr();
}

//写入一个字节
void Send_Byte(uint8_t dat)
{
    
  uint8_t i;
  for (i = 0; i < 8; i++)
  {
    
    OLED_SCL_Clr(); //将时钟信号设置为低电平
    if (dat & 0x80) //将dat的8位从最高位依次写入
    {
    
      OLED_SDA_Set();
    }
    else
    {
    
      OLED_SDA_Clr();
    }

    OLED_SCL_Set();

    OLED_SCL_Clr();
    dat <<= 1;
  }
}

//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(uint8_t dat, uint8_t mode)
{
    
  I2C_Start();
  Send_Byte(0x78);
  I2C_WaitAck();
  if (mode)
  {
    
    Send_Byte(0x40);
  }
  else
  {
    
    Send_Byte(0x00);
  }
  I2C_WaitAck();
  Send_Byte(dat);
  I2C_WaitAck();
  I2C_Stop();
}
#elif (TRANSFER_METHOD == HW_SPI)
//暂未支持
#endif

//反显函数
void OLED_ColorTurn(uint8_t i)
{
    
  if (i == 0)
  {
    
    OLED_WR_Byte(0xA6, OLED_CMD); //正常显示
  }
  if (i == 1)
  {
    
    OLED_WR_Byte(0xA7, OLED_CMD); //反色显示
  }
}

//屏幕旋转180度
void OLED_DisplayTurn(uint8_t i)
{
    
  if (i == 0)
  {
    
    OLED_WR_Byte(0xC8, OLED_CMD); //正常显示
    OLED_WR_Byte(0xA1, OLED_CMD);
  }
  if (i == 1)
  {
    
    OLED_WR_Byte(0xC0, OLED_CMD); //反转显示
    OLED_WR_Byte(0xA0, OLED_CMD);
  }
}

//坐标设置
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
    
  OLED_WR_Byte(0xb0 + y, OLED_CMD);
  OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
  OLED_WR_Byte((x & 0x0f), OLED_CMD);
}
//开启OLED显示
void OLED_Display_On(void)
{
    
  OLED_WR_Byte(0X8D, OLED_CMD); //SET DCDC命令
  OLED_WR_Byte(0X14, OLED_CMD); //DCDC ON
  OLED_WR_Byte(0XAF, OLED_CMD); //DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void)
{
    
  OLED_WR_Byte(0X8D, OLED_CMD); //SET DCDC命令
  OLED_WR_Byte(0X10, OLED_CMD); //DCDC OFF
  OLED_WR_Byte(0XAE, OLED_CMD); //DISPLAY OFF
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{
    
  uint8_t i, n;
  for (i = 0; i < 8; i++)
  {
    
    OLED_WR_Byte(0xb0 + i, OLED_CMD); //设置页地址(0~7)
    OLED_WR_Byte(0x00, OLED_CMD);     //设置显示位置―列低地址
    OLED_WR_Byte(0x10, OLED_CMD);     //设置显示位置―列高地址
    for (n = 0; n < 128; n++)
      OLED_WR_Byte(0, OLED_DATA);
  } //更新显示
}

//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//sizey:选择字体 6x8  8x16
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t sizey)
{
    
  uint8_t c = 0, sizex = sizey / 2;
  uint16_t i = 0, size1;
  if (sizey == 8)
    size1 = 6;
  else
    size1 = (sizey / 8 + ((sizey % 8) ? 1 : 0)) * (sizey / 2);
  c = chr - ' '; //得到偏移后的值
  OLED_Set_Pos(x, y);
  for (i = 0; i < size1; i++)
  {
    
    if (i % sizex == 0 && sizey != 8)
      OLED_Set_Pos(x, y++);
    if (sizey == 8)
      OLED_WR_Byte(asc2_0806[c][i], OLED_DATA); //6X8字号
    else if (sizey == 16)
      OLED_WR_Byte(asc2_1608[c][i], OLED_DATA); //8x16字号
    //		else if(sizey==xx) OLED_WR_Byte(asc2_xxxx[c][i],OLED_DATA);//用户添加字号
    else
      return;
  }
}
//m^n函数
uint32_t oled_pow(uint8_t m, uint8_t n)
{
    
  uint32_t result = 1;
  while (n--)
    result *= m;
  return result;
}
//显示数字
//x,y :起点坐标
//num:要显示的数字
//len :数字的位数
//sizey:字体大小
void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t sizey)
{
    
  uint8_t t, temp, m = 0;
  uint8_t enshow = 0;
  if (sizey == 8)
    m = 2;
  for (t = 0; t < len; t++)
  {
    
    temp = (num / oled_pow(10, len - t - 1)) % 10;
    if (enshow == 0 && t < (len - 1))
    {
    
      if (temp == 0)
      {
    
        OLED_ShowChar(x + (sizey / 2 + m) * t, y, ' ', sizey);
        continue;
      }
      else
        enshow = 1;
    }
    OLED_ShowChar(x + (sizey / 2 + m) * t, y, temp + '0', sizey);
  }
}
//显示一个字符号串
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t sizey)
{
    
  uint8_t j = 0;
  while (chr[j] != '\0')
  {
    
    OLED_ShowChar(x, y, chr[j++], sizey);
    if (sizey == 8)
      x += 6;
    else
      x += sizey / 2;
  }
}
//显示汉字
void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t no, uint8_t sizey)
{
    
  uint16_t i, size1 = (sizey / 8 + ((sizey % 8) ? 1 : 0)) * sizey;
  for (i = 0; i < size1; i++)
  {
    
    if (i % sizey == 0)
      OLED_Set_Pos(x, y++);
    if (sizey == 16)
      OLED_WR_Byte(Hzk[no][i], OLED_DATA); //16x16字号
    //		else if(sizey==xx) OLED_WR_Byte(xxx[c][i],OLED_DATA);//用户添加字号
    else
      return;
  }
}

//显示图片
//x,y显示坐标
//sizex,sizey,图片长宽
//BMP:要显示的图片
void OLED_DrawBMP(uint8_t x, uint8_t y, uint8_t sizex, uint8_t sizey, uint8_t BMP[])
{
    
  uint16_t j = 0;
  uint8_t i, m;
  sizey = sizey / 8 + ((sizey % 8) ? 1 : 0);
  for (i = 0; i < sizey; i++)
  {
    
    OLED_Set_Pos(x, i + y);
    for (m = 0; m < sizex; m++)
    {
    
      OLED_WR_Byte(BMP[j++], OLED_DATA);
    }
  }
}

//初始化SSD1306
void OLED_Init(void)
{
    
#if (TRANSFER_METHOD == HW_IIC)
  I2C_Configuration();
#elif (TRANSFER_METHOD == SW_IIC)
  I2C_SW_Configuration();
#elif (TRANSFER_METHOD == HW_SPI)
  SPI_Configuration();
#endif

  OLED_WR_Byte(0xAE, OLED_CMD); //--turn off oled panel
  OLED_WR_Byte(0x00, OLED_CMD); //---set low column address
  OLED_WR_Byte(0x10, OLED_CMD); //---set high column address
  OLED_WR_Byte(0x40, OLED_CMD); //--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
  OLED_WR_Byte(0x81, OLED_CMD); //--set contrast control register
  OLED_WR_Byte(0xCF, OLED_CMD); // Set SEG Output Current Brightness
  OLED_WR_Byte(0xA1, OLED_CMD); //--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
  OLED_WR_Byte(0xC8, OLED_CMD); //Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
  OLED_WR_Byte(0xA6, OLED_CMD); //--set normal display
  OLED_WR_Byte(0xA8, OLED_CMD); //--set multiplex ratio(1 to 64)
  OLED_WR_Byte(0x3f, OLED_CMD); //--1/64 duty
  OLED_WR_Byte(0xD3, OLED_CMD); //-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
  OLED_WR_Byte(0x00, OLED_CMD); //-not offset
  OLED_WR_Byte(0xd5, OLED_CMD); //--set display clock divide ratio/oscillator frequency
  OLED_WR_Byte(0x80, OLED_CMD); //--set divide ratio, Set Clock as 100 Frames/Sec
  OLED_WR_Byte(0xD9, OLED_CMD); //--set pre-charge period
  OLED_WR_Byte(0xF1, OLED_CMD); //Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  OLED_WR_Byte(0xDA, OLED_CMD); //--set com pins hardware configuration
  OLED_WR_Byte(0x12, OLED_CMD);
  OLED_WR_Byte(0xDB, OLED_CMD); //--set vcomh
  OLED_WR_Byte(0x40, OLED_CMD); //Set VCOM Deselect Level
  OLED_WR_Byte(0x20, OLED_CMD); //-Set Page Addressing Mode (0x00/0x01/0x02)
  OLED_WR_Byte(0x02, OLED_CMD); //
  OLED_WR_Byte(0x8D, OLED_CMD); //--set Charge Pump enable/disable
  OLED_WR_Byte(0x14, OLED_CMD); //--set(0x10) disable
  OLED_WR_Byte(0xA4, OLED_CMD); // Disable Entire Display On (0xa4/0xa5)
  OLED_WR_Byte(0xA6, OLED_CMD); // Disable Inverse Display On (0xa6/a7)
  OLED_Clear();
  OLED_WR_Byte(0xAF, OLED_CMD); /*display ON*/
}

十一、VOFA

#include "vofa.h"
#include "usart.h"

void Float_to_Byte(float f,unsigned char byte[])   
{
    
	FloatLongType fl;
	fl.fdata=f;
	byte[0]=(unsigned char)fl.ldata;
	byte[1]=(unsigned char)(fl.ldata>>8);
	byte[2]=(unsigned char)(fl.ldata>>16);
	byte[3]=(unsigned char)(fl.ldata>>24);
}


void SendDatatoVoFA(u8 byte[],float v_real)//缓冲数组,实际值
{
    
	u8 t_test=0;//四位发送
	u8 send_date[4]={
    0};//发送数据
	

	//发送数据,绘制图像
	Float_to_Byte(v_real,byte);//当前速度
//			Float_to_Byte(num*1.0,byte);
	for(t_test=0;t_test<4;t_test++)
	{
    
		UART_transmitData(EUSCI_A0_BASE, byte[t_test]); 
	}	
			
	send_date[0]=0X00;send_date[1]=0X00;
	send_date[2]=0X80;send_date[3]=0X7f;
	for(t_test=0;t_test<4;t_test++)
	{
    
		UART_transmitData(EUSCI_A0_BASE, send_date[t_test]); 
	}

}


十二、GPIO

#include "motor.h"

/*************************************************
 * 函  数  名:gpio_init
 * 功       能:初始化gpio口
 * 参       数:selectedPort:端口号
 *          selectedPins:引脚号
 *          MODE:输入输出模式选择,在exingpio.h文件枚举
 *          out_value:当设置成输出时,此位设置输出电平1:高电平 0:低电平
 *                    当设置成输入时,此位设置上下拉电阻 1:上拉 0:下拉
 * 注意事项:无
 *************************************************/
void gpio_init(uint_fast8_t selectedPort,uint_fast16_t selectedPins,int MODE,unsigned int out_value)
{
    
    switch(MODE)
    {
    
        case 0:
                       gpio_set_Asout(selectedPort,selectedPins);
                       gpio_disable_Ren(selectedPort,selectedPins);
                       if(out_value)
                           gpio_set_High(selectedPort,selectedPins);
                       else
                           gpio_set_Low(selectedPort,selectedPins);
        break;
        case 1:
                        gpio_set_Asin(selectedPort,selectedPins);
                        gpio_enable_Ren(selectedPort,selectedPins);
                        if(out_value)
                            gpio_set_High(selectedPort,selectedPins);
                        else
                            gpio_set_Low(selectedPort,selectedPins);
        break;
    }
}


/*************************************************
 * 函  数  名:gpio_set_Asout
 * 功       能:将GPIO引脚设置为输出
 * 参       数:selectedPort:端口号
 *          selectedPins:引脚号
 * 注意事项:无
 *************************************************/
void gpio_set_Asout(uint_fast8_t selectedPort,uint_fast16_t selectedPins)
{
    
    switch(selectedPort)
      {
    
          case(GPIO_PORT_P1):P1->DIR |= selectedPins; break;
          case(GPIO_PORT_P2):P2->DIR |= selectedPins; break;
          case(GPIO_PORT_P3):P3->DIR |= selectedPins; break;
          case(GPIO_PORT_P4):P4->DIR |= selectedPins; break;
          case(GPIO_PORT_P5):P5->DIR |= selectedPins; break;
          case(GPIO_PORT_P6):P6->DIR |= selectedPins; break;
          case(GPIO_PORT_P7):P7->DIR |= selectedPins; break;
          case(GPIO_PORT_P8):P8->DIR |= selectedPins; break;
          case(GPIO_PORT_P9):P9->DIR |= selectedPins; break;
          case(GPIO_PORT_P10):P10->DIR |= selectedPins; break;
          default:;
      }
}

/*************************************************
 * 函  数  名:gpio_disable_Ren
 * 功       能:将GPIO引脚上下拉电阻禁能
 * 参       数:selectedPort:端口号
 *          selectedPins:引脚号
 * 注意事项:无
 *************************************************/
void gpio_disable_Ren(uint_fast8_t selectedPort,uint_fast16_t selectedPins)
{
    
    switch(selectedPort)
      {
    
            case(GPIO_PORT_P1):P1->REN &= ~selectedPins; break;
            case(GPIO_PORT_P2):P2->REN &= ~selectedPins; break;
            case(GPIO_PORT_P3):P3->REN &= ~selectedPins; break;
            case(GPIO_PORT_P4):P4->REN &= ~selectedPins; break;
            case(GPIO_PORT_P5):P5->REN &= ~selectedPins; break;
            case(GPIO_PORT_P6):P6->REN &= ~selectedPins; break;
            case(GPIO_PORT_P7):P7->REN &= ~selectedPins; break;
            case(GPIO_PORT_P8):P8->REN &= ~selectedPins; break;
            case(GPIO_PORT_P9):P9->REN &= ~selectedPins; break;
            case(GPIO_PORT_P10):P10->REN &= ~selectedPins; break;
            default:;
      }
}

/*************************************************
 * 函  数  名:gpio_set_High
 * 功       能:将GPIO引脚设置为高电平
 * 参       数:selectedPort:端口号
 *          selectedPins:引脚号
 * 注意事项:当上下拉电阻使能时,该函数可设置使用上拉电阻
 *************************************************/
void gpio_set_High(uint_fast8_t selectedPort,uint_fast16_t selectedPins)
{
    
    switch(selectedPort)
      {
    
            case(GPIO_PORT_P1):P1->OUT |= selectedPins; break;
            case(GPIO_PORT_P2):P2->OUT |= selectedPins; break;
            case(GPIO_PORT_P3):P3->OUT |= selectedPins; break;
            case(GPIO_PORT_P4):P4->OUT |= selectedPins; break;
            case(GPIO_PORT_P5):P5->OUT |= selectedPins; break;
            case(GPIO_PORT_P6):P6->OUT |= selectedPins; break;
            case(GPIO_PORT_P7):P7->OUT |= selectedPins; break;
            case(GPIO_PORT_P8):P8->OUT |= selectedPins; break;
            case(GPIO_PORT_P9):P9->OUT |= selectedPins; break;
            case(GPIO_PORT_P10):P10->OUT |= selectedPins; break;
            default:;
      }
}
/*************************************************
 * 函  数  名:gpio_set_Low
 * 功       能:将GPIO引脚设置为高电平
 * 参       数:selectedPort:端口号
 *          selectedPins:引脚号
 * 注意事项:当上下拉电阻使能时,该函数可设置使用下拉电阻
 *************************************************/
void gpio_set_Low(uint_fast8_t selectedPort,uint_fast16_t selectedPins)
{
    
    switch(selectedPort)
      {
    
            case(GPIO_PORT_P1):P1->OUT &= ~selectedPins; break;
            case(GPIO_PORT_P2):P2->OUT &= ~selectedPins; break;
            case(GPIO_PORT_P3):P3->OUT &= ~selectedPins; break;
            case(GPIO_PORT_P4):P4->OUT &= ~selectedPins; break;
            case(GPIO_PORT_P5):P5->OUT &= ~selectedPins; break;
            case(GPIO_PORT_P6):P6->OUT &= ~selectedPins; break;
            case(GPIO_PORT_P7):P7->OUT &= ~selectedPins; break;
            case(GPIO_PORT_P8):P8->OUT &= ~selectedPins; break;
            case(GPIO_PORT_P9):P9->OUT &= ~selectedPins; break;
            case(GPIO_PORT_P10):P10->OUT &= ~selectedPins; break;
            default:;
      }
}
/*************************************************
 * 函  数  名:gpio_enable_Ren
 * 功       能:将GPIO引脚上下拉电阻使能
 * 参       数:selectedPort:端口号
 *          selectedPins:引脚号
 * 注意事项:无
 *************************************************/
void gpio_enable_Ren(uint_fast8_t selectedPort,uint_fast16_t selectedPins)
{
    
    switch(selectedPort)
      {
    
           case(GPIO_PORT_P1):P1->REN |= selectedPins; break;
           case(GPIO_PORT_P2):P2->REN |= selectedPins; break;
           case(GPIO_PORT_P3):P3->REN |= selectedPins; break;
           case(GPIO_PORT_P4):P4->REN |= selectedPins; break;
           case(GPIO_PORT_P5):P5->REN |= selectedPins; break;
           case(GPIO_PORT_P6):P6->REN |= selectedPins; break;
           case(GPIO_PORT_P7):P7->REN |= selectedPins; break;
           case(GPIO_PORT_P8):P8->REN |= selectedPins; break;
           case(GPIO_PORT_P9):P9->REN |= selectedPins; break;
           case(GPIO_PORT_P10):P10->REN |= selectedPins; break;
           default:;
      }
}

/*************************************************
 * 函  数  名:gpio_set_Asin
 * 功       能:将GPIO引脚设置为输入
 * 参       数:selectedPort:端口号
 *          selectedPins:引脚号
 * 注意事项:无
 *************************************************/
void gpio_set_Asin(uint_fast8_t selectedPort,uint_fast16_t selectedPins)
{
    
    switch(selectedPort)
      {
    
          case(GPIO_PORT_P1):P1->DIR &= ~selectedPins; break;
          case(GPIO_PORT_P2):P2->DIR &= ~selectedPins; break;
          case(GPIO_PORT_P3):P3->DIR &= ~selectedPins; break;
          case(GPIO_PORT_P4):P4->DIR &= ~selectedPins; break;
          case(GPIO_PORT_P5):P5->DIR &= ~selectedPins; break;
          case(GPIO_PORT_P6):P6->DIR &= ~selectedPins; break;
          case(GPIO_PORT_P7):P7->DIR &= ~selectedPins; break;
          case(GPIO_PORT_P8):P8->DIR &= ~selectedPins; break;
          case(GPIO_PORT_P9):P9->DIR &= ~selectedPins; break;
          case(GPIO_PORT_P10):P10->DIR &= ~selectedPins; break;
          default:;
      }
}

十三、Timer32

#include "tim32.h"
#include "usart.h"

void Tim32_0_Int_Init(uint32_t aar, uint8_t psc)
{
    
    MAP_Timer32_initModule(TIMER32_0_BASE, psc, TIMER32_32BIT, TIMER32_PERIODIC_MODE);

    MAP_Timer32_setCount(TIMER32_0_BASE, aar);

    MAP_Timer32_enableInterrupt(TIMER32_0_BASE);

    MAP_Timer32_startTimer(TIMER32_0_BASE, false); //连续计数模式 false

    MAP_Interrupt_enableInterrupt(INT_T32_INT1);
}

/* Timer32 ISR */
void T32_INT1_IRQHandler(void)
{
    
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);

    /*开始填充用户代码*/
    static uint8_t timer_second = 0;

    //一般在频率较高的中断不常用 这个printf比较费时间 这里只是演示
    printf("\r\nTim32_0: %ds Timeout\r\n", ++timer_second);

    /*结束填充用户代码*/
}

void Tim32_1_Int_Init(uint32_t aar, uint8_t psc)
{
    
    MAP_Timer32_initModule(TIMER32_1_BASE, psc, TIMER32_32BIT, TIMER32_PERIODIC_MODE);

    MAP_Timer32_setCount(TIMER32_1_BASE, aar);

    MAP_Timer32_enableInterrupt(TIMER32_1_BASE);

    MAP_Timer32_startTimer(TIMER32_1_BASE, false); //连续计数模式 false

    MAP_Interrupt_enableInterrupt(INT_T32_INT2);
}

/* Timer32 ISR */
void T32_INT2_IRQHandler(void)
{
    
    MAP_Timer32_clearInterruptFlag(TIMER32_1_BASE);
	int i=1;
    /*开始填充用户代码*/
	printf("\r\n\r\nTim32_1: %ds Timeout\r\n\r\n", 16*i++);
    /*结束填充用户代码*/
}

十四、PID

#include"PID.h"
#include"math.h"

//初始化PID结构体参数
void PID_Init(PID * s_PID,PID_VAR_TYPE set_point,PID_VAR_TYPE Proportion,PID_VAR_TYPE Integral, PID_VAR_TYPE Derivative)
{
    
   s_PID->SetPoint = set_point;
   s_PID->Proportion = Proportion;
   s_PID->Integral = Integral;
   s_PID->Derivative = Derivative;
   s_PID->Error = 0;
   s_PID->LastError = 0;
   s_PID->PrevError = 0;
   s_PID->SumError = 0;
   s_PID->LastResult = 0;
   s_PID->Result = 0;
   s_PID->OutMax = DEFAULT_PID_OUT_MAX;
   s_PID->OutMin = DEFAULT_PID_OUT_MIN;
   s_PID->IntegralMax = DEFAULT_PID_INTEGRAL_OUT_MAX;
   s_PID->IntegralMin = DEFAULT_PID_INTEGRAL_OUT_MIN;
}
//设置目标值
void  PID_SetPoint     (PID * s_PID, PID_VAR_TYPE set_point) 
{
    
   s_PID->SetPoint = set_point;
}      
//设置PID输出范围
void  PID_SetOutRange  (PID * s_PID, PID_VAR_TYPE outMax,PID_VAR_TYPE outMin)
{
    
  s_PID->OutMax = outMax;
  s_PID->OutMin = outMin;
}
//设置PID积分范围
void  PID_SetIntegralOutRange(PID * s_PID, PID_VAR_TYPE outMax,PID_VAR_TYPE outMin)
{
    
  s_PID->IntegralMax = outMax;
  s_PID->IntegralMin = outMin;
}
//增量式PID计算
PID_VAR_TYPE Increment_PID_Cal(PID * s_PID,PID_VAR_TYPE now_point)
{
    
    s_PID->LastResult = s_PID->Result;					       // 简单赋值运算	
    //误差计算   
    s_PID->Error = s_PID->SetPoint - now_point;
    //PID计算   
    s_PID->Result = s_PID->LastResult 
                  + s_PID->Proportion  * (s_PID->Error - s_PID->LastError)                          // 比例项
                  + s_PID->Integral    *  s_PID->Error	                                       // 积分项 
                  + s_PID->Derivative  * (s_PID->Error - 2*(s_PID->LastError) + s_PID->PrevError);  // 微分项
   
    s_PID->PrevError = s_PID->LastError;		               // 简单赋值运算
    s_PID->LastError = s_PID->Error; 				       // 简单赋值运算
    //输出限幅
    if(s_PID->Result > s_PID->OutMax)s_PID->Result = s_PID->OutMax;
    else if(s_PID->Result < s_PID->OutMin)s_PID->Result = s_PID->OutMin;
    
    return s_PID->Result;	
}
//位置式PID计算
PID_VAR_TYPE Position_PID_Cal(PID * s_PID,PID_VAR_TYPE now_point)
{
    
    s_PID->LastResult = s_PID->Result;			       // 简单赋值运算
    //误差计算
    s_PID->Error = s_PID->SetPoint - now_point;
    s_PID->SumError += s_PID->Error;                            //积分误差累加
    //积分限幅
    PID_VAR_TYPE IOutValue = s_PID->SumError * s_PID->Integral;
    if(IOutValue > s_PID->IntegralMax)IOutValue = s_PID->IntegralMax;
    else if(IOutValue < s_PID->IntegralMin)IOutValue = s_PID->IntegralMin;
    //PID计算
    s_PID->Result =  s_PID->Proportion  *  s_PID->Error                          // 比例项
                   + IOutValue                                                     // 积分项 
                   + s_PID->Derivative  * (s_PID->Error - s_PID->LastError);     // 微分项
    
    s_PID->PrevError = s_PID->LastError;		                       // 简单赋值运算
    s_PID->LastError = s_PID->Error; 				       // 简单赋值运算
 
    //输出限幅
    if(s_PID->Result > s_PID->OutMax)s_PID->Result = s_PID->OutMax;
    else if(s_PID->Result < s_PID->OutMin)s_PID->Result = s_PID->OutMin;
    
    return s_PID->Result;	
}
//比例外置式PID
PID_VAR_TYPE PID_Cal(PID * s_PID,PID_VAR_TYPE now_point)
{
      
    s_PID->LastResult = s_PID->Result;			       // 简单赋值运算
    //误差计算
    s_PID->Error = s_PID->SetPoint - now_point;
    s_PID->SumError += s_PID->Error;                            //积分误差累加
    //积分限幅
    PID_VAR_TYPE IOutValue = s_PID->SumError * s_PID->Integral;
    if(IOutValue > s_PID->IntegralMax)IOutValue = s_PID->IntegralMax;
    else if(IOutValue < s_PID->IntegralMin)IOutValue = s_PID->IntegralMin;
    //PID计算   
    s_PID->Result = s_PID->Proportion *
       (s_PID->Error + IOutValue + s_PID->Derivative * (s_PID->Error - s_PID->LastError) );
   
    s_PID->PrevError = s_PID->LastError;		                       // 简单赋值运算
    s_PID->LastError = s_PID->Error; 				       // 简单赋值运算
    //输出限幅
    if(s_PID->Result > s_PID->OutMax)s_PID->Result = s_PID->OutMax;
    else if(s_PID->Result < s_PID->OutMin)s_PID->Result = s_PID->OutMin;
    
    return s_PID->Result;
}

源码汇总

全部工程代码联系下方wx即可
可提供一定的技术支持

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Dustinthewine/article/details/131465873

智能推荐

while循环&CPU占用率高问题深入分析与解决方案_main函数使用while(1)循环cpu占用99-程序员宅基地

文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。​​​​​​while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99

【无标题】jetbrains idea shift f6不生效_idea shift +f6快捷键不生效-程序员宅基地

文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效

node.js学习笔记之Node中的核心模块_node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是-程序员宅基地

文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是

数学建模【SPSS 下载-安装、方差分析与回归分析的SPSS实现(软件概述、方差分析、回归分析)】_化工数学模型数据回归软件-程序员宅基地

文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件

利用hutool实现邮件发送功能_hutool发送邮件-程序员宅基地

文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件

docker安装elasticsearch,elasticsearch-head,kibana,ik分词器_docker安装kibana连接elasticsearch并且elasticsearch有密码-程序员宅基地

文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码

随便推点

Python 攻克移动开发失败!_beeware-程序员宅基地

文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware

Swift4.0_Timer 的基本使用_swift timer 暂停-程序员宅基地

文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停

元素三大等待-程序员宅基地

文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待

Java软件工程师职位分析_java岗位分析-程序员宅基地

文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析

Java:Unreachable code的解决方法_java unreachable code-程序员宅基地

文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code

标签data-*自定义属性值和根据data属性值查找对应标签_如何根据data-*属性获取对应的标签对象-程序员宅基地

文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象

推荐文章

热门文章

相关标签