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

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文