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

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法