看代码注释_tmp &= ~(1<<14)_6410 pwm0驱动修改说明

本文详细介绍了如何为S3C6410平台实现一个蜂鸣器驱动程序,包括初始化GPIO配置、设置蜂鸣器开/关状态以及通过ioctl接口进行操作。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <plat/regs-timer.h>
#include <mach/regs-irq.h>
#include <asm/mach/time.h>
#include <linux/clk.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>

#include <mach/map.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>

#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-e.h>
#include <mach/gpio-bank-f.h>
#include <mach/gpio-bank-k.h>

#define DEVICE_NAME     "buzzer"

#define BUZZER_IOCTL_SET_ON _IOW('Q', 0x1, int)
#define BUZZER_IOCTL_SET_OFF _IOW('Q', 0x0, int)

static void buzzer_set_on()
{
 unsigned tmp;
 tmp = readl(S3C64XX_GPFDAT);
 tmp |= 1<<14;                     //gpf14 set high level
 writel(tmp, S3C64XX_GPFDAT);

}

static void buzzer_set_off()
{
 unsigned tmp;
 
 tmp = readl(S3C64XX_GPFDAT);
 tmp &= ~(1<<14);                  //gpf14 set low level
 writel(tmp, S3C64XX_GPFDAT);

}

 

static long s3c64xx_buzzer_ioctl(struct file *filep, unsigned int cmd, long arg)
{
 switch (cmd) {
  case BUZZER_IOCTL_SET_ON:
   buzzer_set_on();
   break;
  case BUZZER_IOCTL_SET_OFF:
   buzzer_set_off();
   break;
  default:
   break;
 }
 return 0;
}


static struct file_operations dev_fops = {
    .owner   = THIS_MODULE,
    .unlocked_ioctl = s3c64xx_buzzer_ioctl,
};

static struct miscdevice misc = {
 .minor = MISC_DYNAMIC_MINOR,
 .name = DEVICE_NAME,
 .fops = &dev_fops,
};

static int __init dev_init(void)
{
 int ret;
 unsigned tmp;
 //init_MUTEX(&lock);
 tmp = readl(S3C64XX_GPFCON);
 tmp &= ~(0x3U << 28);            //set gpf14 is 00
 tmp |=  (0x1U << 28);            //set gpf14 is 01  output
 writel(tmp, S3C64XX_GPFCON);

 tmp = readl(S3C64XX_GPFPUD);
 tmp &= ~(0x3U << 28);            //gpf14 pull-up/down disable
 tmp |=  (0x2U << 28);            //gpf14 pull-up enable
 writel(tmp, S3C64XX_GPFPUD);

 tmp = readl(S3C64XX_GPFDAT);
 tmp &= ~(1<<14);                  //gpf14 set low level
 writel(tmp, S3C64XX_GPFDAT);

 ret = misc_register(&misc);

 printk (DEVICE_NAME"\tinitialized\n");
     return ret;
}

static void __exit dev_exit(void)
{
 misc_deregister(&misc);
}

module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("StarFire WangYuechao");
MODULE_DESCRIPTION("S3C6410 Buzzer Driver");

转载:http://hi.baidu.com/kdwyc/blog/item/6cc28a24a5650d288744f9a6.html

#include&quot;userpar.h&quot; #include&quot;userflash.h&quot; #include&quot;bitband.h&quot; #include&quot;math.h&quot; #include&quot;usersys.h&quot; #include&quot;string.h&quot; #include&quot;useruart_inter.h&quot; #define CTL_TEMP_UP_LIMIT 15//&micro;&yen;&Icirc;&raquo;1&iexcl;&aelig; #define CTL_TEMP_DOWN_LIMIT 13//&micro;&yen;&Icirc;&raquo;1&iexcl;&aelig; #define WARN_TEMP_UP_LIMIT 70//&micro;&yen;&Icirc;&raquo;1&iexcl;&aelig; #define VOL_UP_LIMIT 32.0f// #define VOL_DOWN_LIMIT 22.0 // #define CURR_UP_LIMIT 60.0f//&micro;&yen;&Icirc;&raquo;0.1A typedef struct { uint16_t FPGA_AD[20] ; float rd_power ; //&middot;&acute;&Iuml;&ograve;&sup1;&brvbar;&Acirc;&Ecirc;AD float fd_power ; //&Otilde;&yacute;&Iuml;&ograve;&Iuml;&ograve;&sup1;&brvbar;&Acirc;&Ecirc;AD float vol_a; float curr ; float fan_curr1 ; float fan_curr2 ; int8_t temp ; uint8_t pa_att_set,pa_att_ack; uint8_t pa_ctl_soft_set,pa_ctl_soft_ack;//&Oacute;&ETH;&Egrave;&iacute;&frac14;&thorn;&iquest;&Oslash;&Ouml;&AElig;&sup1;&brvbar;&middot;&Aring;&iquest;&ordf;&AElig;&ocirc;&sup1;&Oslash;&plusmn;&Otilde;&Ecirc;&plusmn;,&plusmn;&Oslash;&ETH;&euml;panel_bon&acute;&ograve;&iquest;&ordf;&sup2;&Aring;&ETH;&ETH; uint8_t vol_warn ;//1 &cedil;&aelig;&frac34;&macr; 0&Otilde;&yacute;&sup3;&pound; uint8_t curr_warn ;//1 &cedil;&aelig;&frac34;&macr; 0&Otilde;&yacute;&sup3;&pound; uint8_t temp_warn ;//1 &cedil;&aelig;&frac34;&macr; 0&Otilde;&yacute;&sup3;&pound; // uint8_t in_power_warn ;//1 &cedil;&aelig;&frac34;&macr; 0&Otilde;&yacute;&sup3;&pound; uint8_t swr_state,swr_warn;//1 &cedil;&aelig;&frac34;&macr; 0&Otilde;&yacute;&sup3;&pound; uint8_t pwm_state,pwm_warn;//1 &cedil;&aelig;&frac34;&macr; 0&Otilde;&yacute;&sup3;&pound; uint8_t fan_ctl_set;//&Iacute;&uml;&sup1;&yacute;&Icirc;&Acirc;&para;&Egrave;&Aring;&ETH;&para;&Iuml;&Ecirc;&Ccedil;&middot;&ntilde;&iquest;&ordf;&AElig;&ocirc;&middot;&ccedil;&raquo;&uacute;,&Oacute;&Eacute;&micro;&yen;&AElig;&not;&raquo;&uacute;&Ouml;&divide;&para;&macr; uint8_t fan_ctl_ack;//FPGA&Oacute;&brvbar;&acute;&eth; uint8_t pa_warn_mcu;//(&sup1;&brvbar;&middot;&Aring;1&micro;&ccedil;&Ocirc;&acute;&micro;&ccedil;&Ntilde;&sup1; &sup1;&brvbar;&middot;&Aring;1&micro;&ccedil;&Ocirc;&acute;&micro;&ccedil;&Aacute;&divide; &sup1;&brvbar;&middot;&Aring;1&Icirc;&Acirc;&para;&Egrave;)&Ograve;&igrave;&sup3;&pound;&ETH;&egrave;&Ograve;&ordf;&Ouml;&divide;&para;&macr;&sup1;&Oslash;&plusmn;&Otilde;&sup1;&brvbar;&middot;&Aring; &Oacute;&Eacute;MCU&Ouml;&divide;&para;&macr; uint8_t pa_warn_fpga;//FPGA&Oacute;&brvbar;&acute;&eth; uint8_t panel_bon ;//0&Ccedil;&aring;&sup3;&yacute;&plusmn;&uml;&frac34;&macr;&times;&acute;&Igrave;&not; 1 &plusmn;&pound;&sup3;&Ouml;&plusmn;&uml;&frac34;&macr;&times;&acute;&Igrave;&not; //uint8_t pa_sw; uint8_t pa_warn; //uint8_t fd_power_bfb; //uint8_t alc_wt_set,alc_wt_ack; //float in_power; //float knob_detec; uint32_t CH1Freq; uint8_t workmode; uint8_t is_valid_vol_data; uint8_t data_Refresh; }ModuParType; ModuParType ModuPar; typedef struct { uint32_t flag_s; uint32_t pa_sw_timer_1s; uint32_t flag_e; }Powerdown_saveparType; Powerdown_saveparType Powerdown_savepar; #define min_power_input_dbm_ch1 -40 #define max_power_input_dbm_ch1 10 #define min_power_output_dbm_ch1 0 #define max_power_output_dbm_ch1 58 #define step_power_input_ch1 1 #define step_power_output_ch1 1 #define input_dbm_ch1_db_len (((max_power_input_dbm_ch1-min_power_input_dbm_ch1)/step_power_input_ch1 ) + 1) #define output_dbm_ch1_db_len (((max_power_output_dbm_ch1-min_power_output_dbm_ch1)/step_power_output_ch1) + 1) typedef struct { uint32_t flag_s; float ch1_jb_fd_power[100]; float ch1_jb_dlt[100]; uint32_t flag_e; }swrpar_Type; swrpar_Type swrpar; typedef struct { uint32_t flag_s; float ch1_input__power_vol[50][100]; float ch1_output_power_vol[50][100]; uint32_t flag_e; }powercalpar_Type; powercalpar_Type powercalpar; float tmp_power_vol_ch1_input[100]; float tmp_power_vol_ch1_output[100]; #define det_len 10 typedef struct { float fd_power[det_len]; float rd_power[det_len]; // float in_power[det_len]; float avg_fd,avg_rd; float sum_fd,sum_rd; uint32_t cnt; }powerdetType; powerdetType powerdet; #define vol_curr_avg_len 40 typedef struct { float vol_a_code[vol_curr_avg_len]; //float vol_b_code[vol_curr_avg_len]; float curr_code[vol_curr_avg_len]; float fun_curr_code[vol_curr_avg_len]; float avg_vol_a,avg_curr,avg_fun_curr; float sum_vol_a,sum_curr,sum_fun_curr; uint32_t cnt; }volcurr_detType; volcurr_detType volcurr_det; //void userpar_SetPASw(uint8_t tmp) //{ // if(ModuPar.pa_warn &gt; 0) // { // ModuPar.pa_sw = 0; // } // else // { // ModuPar.pa_sw = tmp; // } //} //uint8_t userpar_GetPASw(void) //{ // return ModuPar.pa_sw; //} void userpar_SetPACtl_Soft(uint8_t tmp) { ModuPar.pa_ctl_soft_set = tmp; ModuPar.pa_warn_mcu = 0; ModuPar.vol_warn = 0; ModuPar.curr_warn = 0; ModuPar.temp_warn = 0; ModuPar.pa_warn = 0; ModuPar.swr_warn = 0; ModuPar.pwm_warn = 0; ModuPar.pa_ctl_soft_ack = ModuPar.pa_ctl_soft_set + 1; useruart_inter_Set(cmd02,ModuPar.pa_ctl_soft_set); } void userpar_SetPAAtt_Soft(uint8_t tmp) { if(tmp &gt; MAX_ATT) { tmp = MAX_ATT; } ModuPar.pa_att_set = tmp; } uint8_t userpar_GetPAAtt_Soft(void) { return ModuPar.pa_att_set; } void userpar_AckPAAtt_Soft(uint8_t tmp) { ModuPar.pa_att_ack = tmp; } uint8_t userpar_Get_AckPAAtt_Soft(void) { return ModuPar.pa_att_ack; } uint8_t userpar_GetPACtl_Soft(void) { return ModuPar.pa_ctl_soft_set; } void userpar_AckPACtl_Soft(uint8_t tmp) { ModuPar.pa_ctl_soft_ack = tmp; } uint8_t userpar_Get_AckPACtl_Soft(void) { return ModuPar.pa_ctl_soft_ack; } void userpar_SetPanle_Bon(uint8_t Bon) { if(Bon == 1) { ModuPar.pa_warn_mcu = 0; ModuPar.vol_warn = 0; ModuPar.curr_warn = 0; ModuPar.temp_warn = 0; ModuPar.swr_warn = 0; ModuPar.pwm_warn = 0; ModuPar.pa_ctl_soft_set = 0; ModuPar.pa_ctl_soft_ack = 0; ModuPar.pa_warn = 0; } // else // { // if((ModuPar.panel_bon == 0) &amp;&amp; (Bon == 1)) // { // ModuPar.pa_ctl_soft_set = 1; // } // } ModuPar.panel_bon = Bon; } uint8_t userpar_GetPanle_Bon(void) { return ModuPar.panel_bon; } uint16_t userpar_GetFD_Power(void) { return ModuPar.fd_power*10; } uint16_t userpar_GetRD_Power(void) { return ModuPar.rd_power*10; } uint16_t userpar_GetPA_Vol(void) { // if(ModuPar.vol_a &gt; ModuPar.vol_b) // { // return ModuPar.vol_a*10; // } // else // { // return ModuPar.vol_b*10; // } return ModuPar.vol_a*10.0f; } uint16_t userpar_GetPA_Curr(void) { return ModuPar.curr*10; } uint8_t userpar_GetPA_State(void) { return (ModuPar.swr_state &lt;&lt; 4) | (ModuPar.pwm_state &lt;&lt; 3) | (ModuPar.vol_warn &lt;&lt; 2) | (ModuPar.curr_warn &lt;&lt; 1) | (ModuPar.temp_warn &lt;&lt; 0); } int8_t userpar_GetTemp(void) { return ModuPar.temp; } uint8_t userpar_GetFun1_Curr(void) { return ModuPar.fan_curr1*10; } uint8_t userpar_GetFun2_Curr(void) { return ModuPar.fan_curr1*10; } uint8_t userpar_Get_Ack_PAState(void) { return ModuPar.pa_warn_fpga; } uint8_t userpar_Get_Set_PAState(void) { return ModuPar.pa_warn_mcu; } uint8_t userpar_Get_Ack_FunCtl(void) { return ModuPar.fan_ctl_ack; } uint8_t userpar_Get_Set_FunCtl(void) { return ModuPar.fan_ctl_set; } void userpar_Ack_PACtl(uint8_t tmp) { ModuPar.pa_warn_fpga = tmp; } void userpar_Ack_FunCtl(uint8_t tmp) { ModuPar.fan_ctl_ack = tmp; } void userpar_Init(void) { userpar_loadCfg(); userpar_SetFreq(100); ModuPar.fan_ctl_set = 1; ModuPar.pa_warn_mcu = 0; ModuPar.fan_ctl_ack = ModuPar.fan_ctl_set + 1; ModuPar.pa_warn_fpga = ModuPar.pa_warn_mcu + 1; ModuPar.panel_bon = 1; ModuPar.swr_warn = 0; ModuPar.pwm_warn = 0; ModuPar.vol_warn = 0; ModuPar.curr_warn = 0; ModuPar.temp_warn = 0; ModuPar.pa_warn = 0; ModuPar.pa_ctl_soft_set = 0; ModuPar.pa_ctl_soft_ack = ModuPar.pa_ctl_soft_set + 1; ///ModuPar.in_power_warn = 0; //ModuPar.alc_wt_set = 0; // ModuPar.alc_wt_ack = ModuPar.alc_wt_set + 1; ModuPar.data_Refresh = FALSE; userpar_Set_workmode(normal_work_mode); userpar_loadCfg_powerdownpar(); userpar_Erase_powerdownpar(); UserTimer_SetPeroid(TIMER_PA_OPEN_PERIOD,TIMER_PA_OPEN_OPT); UserTimer_SetPeroid(TIMER_ABNORMAL_PERIOD,TIMER_ABNORMAL_OPT); ModuPar.is_valid_vol_data = FALSE; } void userpar_SetFPGA_AD(uint8_t ad_index,uint16_t AD_Value) { ModuPar.FPGA_AD[ad_index] = AD_Value; if(ad_index == 13) { ModuPar.data_Refresh = TRUE; } } void userpar_Set_FPGA_ACK_state(uint8_t swr_state,uint8_t pwm_state) { //ModuPar.swr_state = 0; //ModuPar.pwm_state = 0; } void userpar_SetTemp(int8_t temp) { //ModuPar.temp = temp; } //uint8_t *userpar_advol_input_ch1(void) //{ // return (uint8_t*)&amp;powerdet.avg_in; //} uint8_t *userpar_advol_output_ch1(void) { return (uint8_t*)&amp;powerdet.avg_fd; } void userpar_AbNormal_Handle(void) { double vol = ModuPar.vol_a; if(UserTimer_InqIsTrigger(TIMER_ABNORMAL_OPT) == TRUE) { ModuPar.is_valid_vol_data = TRUE; } if(ModuPar.is_valid_vol_data == FALSE) { return; } // if(ModuPar.pa_sw == 0) // { // return; // } if(ModuPar.temp &gt; CTL_TEMP_UP_LIMIT) { ModuPar.fan_ctl_set = 1; } else if(ModuPar.temp &lt; CTL_TEMP_DOWN_LIMIT) { ModuPar.fan_ctl_set = 0; } if(vol &gt;= VOL_UP_LIMIT) { ModuPar.vol_warn = 1; ModuPar.pa_warn_mcu = 1; } else if(vol &lt;= VOL_DOWN_LIMIT) { ModuPar.vol_warn = 1; ModuPar.pa_warn_mcu = 1; } if(ModuPar.temp &gt;= WARN_TEMP_UP_LIMIT) { ModuPar.temp_warn = 1; ModuPar.pa_warn_mcu = 1; } if(ModuPar.pwm_state &gt; 0) { ModuPar.pwm_warn = 1; ModuPar.pa_warn_mcu = 1; } // if(ModuPar.in_power &gt;= IN_POWER_MAX) // { // ModuPar.in_power_warn = 1; // ModuPar.pa_warn_mcu = 1; // } if(ModuPar.swr_state &gt; 0) { ModuPar.swr_warn = 1; ModuPar.pa_warn_mcu = 1; } if(ModuPar.pa_warn_mcu &gt; 0) { ModuPar.pa_ctl_soft_set = 0; ModuPar.pa_ctl_soft_ack = 0; } ModuPar.pa_warn = (ModuPar.vol_warn&lt;&lt;4) | (ModuPar.curr_warn&lt;&lt;3) | (ModuPar.temp_warn &lt;&lt; 2) | (ModuPar.pwm_warn &lt;&lt; 1) | (ModuPar.swr_warn &lt;&lt; 0); } uint8_t userpar_getPaState(void) { return ModuPar.pa_warn; } void userpar_ParCal_Handle(void) { float vol; //float dlt_bfb; uint16_t curr_code; uint32_t i =0; if(ModuPar.data_Refresh == FALSE) { return; } ModuPar.data_Refresh = FALSE; ModuPar.temp = (ModuPar.FPGA_AD[11]*2.5f*2.0f/4095.0f - 0.5f)/0.01f; if(powerdet.cnt &gt;= det_len) { for(i = 0;i &lt; (det_len - 1);i++) { powerdet.fd_power[i] = powerdet.fd_power[i+1]; powerdet.rd_power[i] = powerdet.rd_power[i+1]; } powerdet.fd_power[(det_len - 1)] = ModuPar.FPGA_AD[9]; powerdet.rd_power[(det_len - 1)] = ModuPar.FPGA_AD[8]; } else { powerdet.fd_power[powerdet.cnt] = ModuPar.FPGA_AD[9]; powerdet.rd_power[powerdet.cnt] = ModuPar.FPGA_AD[8]; powerdet.cnt++; } powerdet.sum_fd = 0; powerdet.sum_rd = 0; for(i = 0;i &lt; powerdet.cnt;i++) { powerdet.sum_fd = powerdet.sum_fd + powerdet.fd_power[i]; powerdet.sum_rd = powerdet.sum_rd + powerdet.rd_power[i]; } powerdet.avg_fd = powerdet.sum_fd*2.5f/4095.0f/powerdet.cnt; powerdet.avg_rd = powerdet.sum_rd*2.5f/4095.0f/powerdet.cnt; ModuPar.fd_power = userpar_compute_outputpower_ch1(powerdet.avg_fd); ModuPar.rd_power = userpar_compute_outputpower_ch1(powerdet.avg_rd); uint8_t *pcal_fd; uint8_t *pcal_dlt_thr; pcal_fd = userpar_correct_ch1_jb_fd_power(); pcal_dlt_thr = userpar_correct_ch1_jb_dlt(); if((ModuPar.fd_power &gt; (*pcal_fd)) &amp;&amp; (ModuPar.fd_power &lt; (ModuPar.rd_power + (*pcal_dlt_thr)))) { ModuPar.swr_state = 1; } curr_code = ModuPar.FPGA_AD[0] + ModuPar.FPGA_AD[1] + ModuPar.FPGA_AD[2] + ModuPar.FPGA_AD[3] + ModuPar.FPGA_AD[4] + ModuPar.FPGA_AD[5] + ModuPar.FPGA_AD[6] + ModuPar.FPGA_AD[7]; if(volcurr_det.cnt &gt;= vol_curr_avg_len) { for(i = 0;i &lt; (vol_curr_avg_len - 1);i++) { volcurr_det.vol_a_code[i] = volcurr_det.vol_a_code[i+1]; //volcurr_det.vol_b_code[i] = volcurr_det.vol_b_code[i+1]; volcurr_det.curr_code[i] = volcurr_det.curr_code[i+1]; volcurr_det.fun_curr_code[i] = volcurr_det.fun_curr_code[i+1]; } volcurr_det.vol_a_code[(vol_curr_avg_len - 1)] = ModuPar.FPGA_AD[10]; //volcurr_det.vol_b_code[(vol_curr_avg_len - 1)] = ModuPar.FPGA_AD[6]; volcurr_det.curr_code[(vol_curr_avg_len - 1)] = curr_code;//ModuPar.FPGA_AD[0]; volcurr_det.fun_curr_code[(vol_curr_avg_len - 1)] = ModuPar.FPGA_AD[12]; } else { volcurr_det.vol_a_code[volcurr_det.cnt] = ModuPar.FPGA_AD[10]; //volcurr_det.vol_b_code[volcurr_det.cnt] = ModuPar.FPGA_AD[6]; volcurr_det.curr_code[volcurr_det.cnt] = curr_code;//ModuPar.FPGA_AD[0]; volcurr_det.fun_curr_code[volcurr_det.cnt] = ModuPar.FPGA_AD[12]; volcurr_det.cnt++; } volcurr_det.sum_vol_a = 0; //volcurr_det.sum_vol_b = 0; volcurr_det.sum_curr = 0; volcurr_det.sum_fun_curr = 0; for(i = 0;i &lt; volcurr_det.cnt;i++) { volcurr_det.sum_vol_a = volcurr_det.sum_vol_a + volcurr_det.vol_a_code[i]; //volcurr_det.sum_vol_b = volcurr_det.sum_vol_b + volcurr_det.vol_b_code[i]; volcurr_det.sum_curr = volcurr_det.sum_curr + volcurr_det.curr_code[i]; volcurr_det.sum_fun_curr = volcurr_det.sum_fun_curr + volcurr_det.fun_curr_code[i]; } volcurr_det.avg_vol_a = volcurr_det.sum_vol_a/volcurr_det.cnt; //volcurr_det.avg_vol_b = volcurr_det.sum_vol_b/volcurr_det.cnt; volcurr_det.avg_curr = volcurr_det.sum_curr/volcurr_det.cnt; volcurr_det.avg_fun_curr = volcurr_det.sum_fun_curr/volcurr_det.cnt; vol = (volcurr_det.avg_curr*2.5f/4095.f); vol = vol*6.0f;//2.0f&middot;&Ouml;&Ntilde;&sup1;&plusmn;&para;&Ecirc;&yacute; if(vol &gt;= 19.968f)//19.52f-&gt;8&cedil;&ouml;&Iacute;&uml;&micro;&Agrave;0&micro;&ccedil;&Aacute;&divide;&micro;&ccedil;&Ntilde;&sup1;(AD&sup2;&Eacute;&frac14;&macr;&micro;&ccedil;&Ntilde;&sup1;*2(&middot;&Ouml;&Ntilde;&sup1;&plusmn;&para;&Ecirc;&yacute;)*8(8&Iacute;&uml;&micro;&Agrave;)) { ModuPar.curr = (vol - 19.968f)*1.166f/0.1f; } else { ModuPar.curr = 0; } ModuPar.fan_curr1 = volcurr_det.avg_fun_curr*2.5f/4095; if(ModuPar.fan_curr1 &gt; 1.229f) { ModuPar.fan_curr1 = (ModuPar.fan_curr1 - 1.229f)*2/0.18f; } else { ModuPar.fan_curr1 = 0; } ModuPar.curr = ModuPar.curr + ModuPar.fan_curr1; ModuPar.vol_a = (volcurr_det.avg_vol_a*2.5f/4095.0f) * 37.0f; } void userpar_pa_open_handle(void) { if(UserTimer_InqIsTrigger(TIMER_PA_OPEN_OPT) == TRUE) { UserTimer_SetPeroid(TIMER_PA_OPEN_PERIOD,TIMER_PA_OPEN_OPT); if(ModuPar.pa_ctl_soft_set == 1) { Powerdown_savepar.pa_sw_timer_1s++; } } } uint32_t userpar_get_pa_run_timer_1s(void)//0.1&ETH;&iexcl;&Ecirc;&plusmn; { return Powerdown_savepar.pa_sw_timer_1s/360;//0.1&ETH;&iexcl;&Ecirc;&plusmn; } void userpar_handle(void) { userpar_pa_open_handle(); userpar_ParCal_Handle(); userpar_compute_inputpower_ch1_base_vol(); userpar_compute_outputpower_ch1_base_vol(); userpar_AbNormal_Handle(); } void userpar_SavePower_vol(void) { userflash_Erase(CORRECT_DATA_SAVESECTOR_CAL_5); userflash_Write(0,(uint8_t*)&amp;powercalpar,sizeof(powercalpar_Type),CORRECT_DATA_SAVEADDR_CAL_5); } #define MIN_FREQ 18000 #define MAX_FREQ 40000 void userpar_SetFreq(uint32_t freq) { if((freq &lt; MIN_FREQ) || (freq &gt; MAX_FREQ)) { return; } ModuPar.CH1Freq = freq; } uint32_t userpar_GetFreq(void) { return ModuPar.CH1Freq; } uint32_t userpar_freqindex_correct(void) { uint32_t freq_index; if((ModuPar.CH1Freq &lt; 150) &amp;&amp; (ModuPar.CH1Freq &gt;= 100)) { freq_index = 0; } else if((ModuPar.CH1Freq &lt; 200) &amp;&amp; (ModuPar.CH1Freq &gt;= 150)) { freq_index = 1; } else if((ModuPar.CH1Freq &lt; 500) &amp;&amp; (ModuPar.CH1Freq &gt;= 200)) { freq_index = 2; } else if((ModuPar.CH1Freq &lt; 1000) &amp;&amp; (ModuPar.CH1Freq &gt;= 500)) { freq_index = 3; } else if((ModuPar.CH1Freq &lt; 5000) &amp;&amp; (ModuPar.CH1Freq &gt;= 1000)) { freq_index = 4; } else if((ModuPar.CH1Freq &lt; 10000) &amp;&amp; (ModuPar.CH1Freq &gt;= 5000)) { freq_index = 5; } else if((ModuPar.CH1Freq &lt; 20000) &amp;&amp; (ModuPar.CH1Freq &gt;= 10000)) { freq_index = 6; } else if((ModuPar.CH1Freq &lt; 50000) &amp;&amp; (ModuPar.CH1Freq &gt;= 20000)) { freq_index = 7; } else if((ModuPar.CH1Freq &lt; 100000) &amp;&amp; (ModuPar.CH1Freq &gt;= 50000)) { freq_index = 8; } else if((ModuPar.CH1Freq &lt; 200000) &amp;&amp; (ModuPar.CH1Freq &gt;= 100000)) { freq_index = 9; } else if((ModuPar.CH1Freq &lt; 300000) &amp;&amp; (ModuPar.CH1Freq &gt;= 200000)) { freq_index = 10; } else if((ModuPar.CH1Freq &lt; 400000) &amp;&amp; (ModuPar.CH1Freq &gt;= 300000)) { freq_index = 11; } else { freq_index = 12; } return freq_index; } uint8_t *userpar_correct_detectvol_inputpower_ch1(int8_t power_dbm) { uint16_t freq_index,power_index; freq_index = userpar_freqindex_correct(); power_index = (power_dbm-min_power_input_dbm_ch1)/step_power_input_ch1; return (uint8_t*)&amp;powercalpar.ch1_input__power_vol[freq_index][power_index]; } uint8_t *userpar_correct_detectvol_outputpower_ch1(int8_t power_dbm) { uint16_t freq_index,power_index; freq_index = userpar_freqindex_correct(); power_index = (power_dbm-min_power_output_dbm_ch1)/step_power_output_ch1; return (uint8_t*)&amp;powercalpar.ch1_output_power_vol[freq_index][power_index]; } void userpar_compute_inputpower_ch1_base_vol(void) { uint16_t index,i; float vol_cal; double Divide_0_freq; double step_freq = 1; index = userpar_freqindex_correct(); for(i = 0;i &lt; input_dbm_ch1_db_len;i++) { if(index == 0) { Divide_0_freq = 100.0f; step_freq = 50.0f; } else if(index == 1) { Divide_0_freq = 150.0f; step_freq = 50.0f; } else if(index == 2) { Divide_0_freq = 200.0f; step_freq = 300.0f; } else if(index == 3) { Divide_0_freq = 500.0f; step_freq = 500.0f; } else if(index == 4) { Divide_0_freq = 1000.0f; step_freq = 4000.0f; } else if(index == 5) { Divide_0_freq = 5000.0f; step_freq = 5000.0f; } else if(index == 6) { Divide_0_freq = 10000.0f; step_freq = 10000.0f; } else if(index == 7) { Divide_0_freq = 20000.0f; step_freq = 30000.0f; } else if(index == 8) { Divide_0_freq = 50000.0f; step_freq = 50000.0f; } else if(index == 9) { Divide_0_freq = 100000.0f; step_freq = 100000.0f; } else if(index == 10) { Divide_0_freq = 200000.0f; step_freq = 100000.0f; } else if(index == 11) { Divide_0_freq = 300000.0f; step_freq = 100000.0f; } else if(index == 12) { Divide_0_freq = 400000.0f; step_freq = 0; } if(index == 12) { vol_cal = powercalpar.ch1_input__power_vol[index][i]; } else { vol_cal = powercalpar.ch1_input__power_vol[index][i] + (powercalpar.ch1_input__power_vol[index + 1][i] - powercalpar.ch1_input__power_vol[index][i])*(ModuPar.CH1Freq-Divide_0_freq)/step_freq; } tmp_power_vol_ch1_input[i] = vol_cal; } } void userpar_compute_outputpower_ch1_base_vol(void) { uint16_t index,i; float vol_cal; double Divide_0_freq; double step_freq = 1; index = userpar_freqindex_correct(); for(i = 0;i &lt; output_dbm_ch1_db_len;i++) { if(index == 0) { Divide_0_freq = 100.0f; step_freq = 50.0f; } else if(index == 1) { Divide_0_freq = 150.0f; step_freq = 50.0f; } else if(index == 2) { Divide_0_freq = 200.0f; step_freq = 300.0f; } else if(index == 3) { Divide_0_freq = 500.0f; step_freq = 500.0f; } else if(index == 4) { Divide_0_freq = 1000.0f; step_freq = 4000.0f; } else if(index == 5) { Divide_0_freq = 5000.0f; step_freq = 5000.0f; } else if(index == 6) { Divide_0_freq = 10000.0f; step_freq = 10000.0f; } else if(index == 7) { Divide_0_freq = 20000.0f; step_freq = 30000.0f; } else if(index == 8) { Divide_0_freq = 50000.0f; step_freq = 50000.0f; } else if(index == 9) { Divide_0_freq = 100000.0f; step_freq = 100000.0f; } else if(index == 10) { Divide_0_freq = 200000.0f; step_freq = 100000.0f; } else if(index == 11) { Divide_0_freq = 300000.0f; step_freq = 100000.0f; } else if(index == 12) { Divide_0_freq = 400000.0f; step_freq = 0.0f; } if(index == 12) { vol_cal = powercalpar.ch1_output_power_vol[index][i]; } else { vol_cal = powercalpar.ch1_output_power_vol[index][i] + (powercalpar.ch1_output_power_vol[index + 1][i] - powercalpar.ch1_output_power_vol[index][i])*(ModuPar.CH1Freq-Divide_0_freq)/step_freq; } tmp_power_vol_ch1_output[i] = vol_cal; } } float userpar_compute_inputpower_ch1(float detect_vol) { uint16_t i; float power_dbm,dlt_db; if(detect_vol &gt;= tmp_power_vol_ch1_input[input_dbm_ch1_db_len-1]) { power_dbm = max_power_input_dbm_ch1; } else if(detect_vol &lt;= tmp_power_vol_ch1_input[0]) { power_dbm = min_power_input_dbm_ch1; } else { for(i = 0;i &lt; (input_dbm_ch1_db_len - 1);i++) { if((detect_vol &lt;= tmp_power_vol_ch1_input[i+1]) &amp;&amp; (detect_vol &gt;= tmp_power_vol_ch1_input[i])) { dlt_db = (detect_vol - tmp_power_vol_ch1_input[i])/(tmp_power_vol_ch1_input[i+1] - tmp_power_vol_ch1_input[i]); power_dbm = min_power_input_dbm_ch1 + i + dlt_db; break; } } } return power_dbm; } float userpar_compute_outputpower_ch1(float detect_vol) { uint16_t i; float power_dbm,dlt_db; if(detect_vol &gt;= tmp_power_vol_ch1_output[output_dbm_ch1_db_len-1]) { power_dbm = max_power_output_dbm_ch1; } else if(detect_vol &lt;= tmp_power_vol_ch1_output[0]) { power_dbm = min_power_output_dbm_ch1; } else { for(i = 0;i &lt; (output_dbm_ch1_db_len - 1);i++) { if((detect_vol &lt;= tmp_power_vol_ch1_output[i+1]) &amp;&amp; (detect_vol &gt;= tmp_power_vol_ch1_output[i])) { dlt_db = (detect_vol - tmp_power_vol_ch1_output[i])/(tmp_power_vol_ch1_output[i+1] - tmp_power_vol_ch1_output[i]); power_dbm = min_power_output_dbm_ch1 + i + dlt_db; break; } } } //power_dbm = 12.0f; return power_dbm; } void userpar_loadCfg(void) { uint8_t i,j; userflash_Read(0,(uint8_t*)&amp;powercalpar,sizeof(powercalpar_Type),CORRECT_DATA_SAVEADDR_CAL_5); if((powercalpar.flag_s != 123456789) || (powercalpar.flag_e != 123456789)) { powercalpar.flag_s = 123456789; powercalpar.flag_e = 123456789; for( j = 0;j &lt; 50;j++) { for( i = 0;i &lt; 100;i++) { powercalpar.ch1_input__power_vol[j][i] = 2.5f; powercalpar.ch1_output_power_vol[j][i] = 2.5f; } } } userflash_Read(0,(uint8_t*)&amp;swrpar,sizeof(swrpar_Type),CORRECT_DATA_SAVEADDR_CAL_6); if((swrpar.flag_s != 123456789) || (swrpar.flag_e != 123456789)) { swrpar.flag_s = 123456789; swrpar.flag_e = 123456789; for(j = 0;j &lt; 50;j++) { swrpar.ch1_jb_dlt[j] = 2; swrpar.ch1_jb_fd_power[j] = 43; } } } uint8_t *userpar_correct_ch1_jb_fd_power(void) { uint16_t freq_index; freq_index = 0; return (uint8_t*)&amp;swrpar.ch1_jb_fd_power[freq_index]; } uint8_t *userpar_correct_ch1_jb_dlt(void) { uint16_t freq_index; freq_index = 0; return (uint8_t*)&amp;swrpar.ch1_jb_dlt[freq_index]; } void userpar_Save_swrPar(void) { userflash_Erase(CORRECT_DATA_SAVESECTOR_CAL_6); userflash_Write(0,(uint8_t*)&amp;swrpar,sizeof(swrpar_Type),CORRECT_DATA_SAVEADDR_CAL_6); } void userpar_Erase_mcu_update_pack(void) { userflash_Erase(MCU_UPDATE_PACK_SAVESECTOR); } void userpar_write_mcu_update_pack(uint32_t pack_bytes,uint8_t *buf,uint32_t offset_addr) { userflash_Write(offset_addr,(uint8_t*)buf,pack_bytes,MCU_UPDATE_PACK_SAVEADDR); } void userpar_write_mcu_update_bytes(uint32_t total_pack_bytes,uint32_t offset_addr) { userflash_Write(offset_addr,(uint8_t*)&amp;total_pack_bytes,4,MCU_UPDATE_PACK_SAVEADDR); } void userpar_write_mcu_update_flag_write(uint32_t offset_addr,uint32_t mcu_update_flag) { userflash_Write(offset_addr,(uint8_t*)&amp;mcu_update_flag,4,MCU_UPDATE_PACK_SAVEADDR); } uint8_t userpar_Get_workmode(void) { return ModuPar.workmode; } uint8_t userpar_Set_workmode(uint32_t tmp) { if(tmp == normal_work_mode) { ModuPar.workmode = tmp; return TRUE; } else if(tmp == uddate_work_mode) { ModuPar.workmode = tmp; return TRUE; } return FALSE; } void userpar_loadCfg_powerdownpar(void) { uint16_t i,j; userflash_Read(0,(uint8_t*)&amp;Powerdown_savepar,sizeof(Powerdown_saveparType),CORRECT_DATA_SAVEADDR_CAL_4); if((Powerdown_savepar.flag_s != 123456789) || (Powerdown_savepar.flag_e != 123456789)) { Powerdown_savepar.flag_s = 123456789; Powerdown_savepar.flag_e = 123456789; Powerdown_savepar.pa_sw_timer_1s = 0; } } void userpar_Erase_powerdownpar(void) { userflash_Erase(CORRECT_DATA_SAVESECTOR_CAL_4); } void userpar_SaveCfg_powerdownpar(void) { //userflash_Erase(CORRECT_DATA_SAVESECTOR_CAL_4); userflash_Write(0,(uint8_t*)&amp;Powerdown_savepar,sizeof(Powerdown_saveparType),CORRECT_DATA_SAVEADDR_CAL_4); } void HAL_PWR_PVDCallback(void) { userpar_SaveCfg_powerdownpar(); }分析这段arm单片机代码
10-28
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include &quot;main.h&quot; #include &quot;adc.h&quot; #include &quot;dma.h&quot; #include &quot;i2c.h&quot; #include &quot;tim.h&quot; #include &quot;usart.h&quot; #include &quot;gpio.h&quot; /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include &lt;stdarg.h&gt; #include &lt;stdio.h&gt; #include &lt;string.h&gt; #include &quot;Adamlib_Button.h&quot; #include &quot;oled.h&quot; #include &quot;filter_channel.h&quot; #include &quot;math.h&quot; // PWM开环步进 #define PWM_Step_long_Biger 20 #define PWM_Step_long_Min 1 // 目标主路输出 #define I_Target 3.0f // 伪PID死区 #define PID_Dead_Biger 0.8f #define PID_Dead_Min 0.05f /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ // 伪PID误差 float V1_Erro; float V2_Erro; float V3_Erro; uint32_t PWM_FREQUENCY = 20000; //50KHz uint32_t PWM_PERIOD = 8400; //ARR值,对应100%占空比 // 初始PWM占空比 uint32_t PWM_DUTY_CH1 = 4200; //通道1初始占空比50% uint32_t PWM_DUTY_CH2 = 4200; //通道2初始占空比50% uint32_t PWM_DUTY_CH3 = 4200; //通道3初始占空比50% uint32_t phase1; //相位偏移10度 uint32_t phase2; //相位偏移130度 uint32_t phase3; //相位偏移250度 uint32_t ccr_ch1[2]; //相位偏移0度 uint32_t ccr_ch2[2]; //相位偏移120度 uint32_t ccr_ch3[2]; //相位偏移240度 //相关标志位 uint8_t flag_PWM = 0; uint8_t flag_OLED = 0; uint8_t PWM_CH_Flage = 1; //占空比通道标志位 //OLED显示数据缓冲区 char message1[20] = &quot;&quot;; char message2[20] = &quot;&quot;; char message3[20] = &quot;&quot;; char message4[20] = &quot;&quot;; /* 存放ADC存入的值 5个通道 */ uint16_t adc_dma_buf[5]; float Vref; //基准电压 float PWM_V1; //第一路输出电压 float PWM_V2; //第二路输出电压 float PWM_V3; //第三路输出电压 float PWM_All; //总输出 float Vout_Target = I_Target / 3; //三路共同目标输出电压 //滤波器 FilterChannel filter_channel1; //第一路输出电压 FilterChannel filter_channel2; //第二路输出电压 FilterChannel filter_channel3; //第三路输出电压 FilterChannel filter_channel4; //第主路输出电压 //长按速度因子 int speed_factor; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ static void UART_Printf(const char *format, ...) { char tmp[128]; va_list argptr; va_start(argptr, format); vsprintf((char* )tmp, format, argptr); va_end(argptr); HAL_UART_Transmit(&amp;huart1, (const uint8_t *)&amp;tmp, strlen(tmp), HAL_MAX_DELAY); } //按键处理函数 void Button_Process(void); //设置PWM占空比并且保证相位对 void Settings_PWM(void); uint32_t calc_phase(uint32_t angle_deg) { // 1. 角度归一化到[0, 360) angle_deg %= 360; // 2. 直接映射到[0, PWM_PERIOD]范围(避免负角度) uint32_t phase = (uint32_t)((uint64_t)PWM_PERIOD * angle_deg / 360); // 3. 相位值安全钳位 return (phase &lt; PWM_PERIOD) ? phase : PWM_PERIOD - 1; } // 更新通道1的CCR值 void Update_Channel1_CCR(void) { ccr_ch1[0] = phase1 - 1; ccr_ch1[1] = (phase1 + PWM_DUTY_CH1) % PWM_PERIOD; } // 更新通道2的CCR值 void Update_Channel2_CCR(void) { ccr_ch2[0] = phase2 - 1; ccr_ch2[1] = (phase2 + PWM_DUTY_CH2) % PWM_PERIOD; } // 更新通道3的CCR值 void Update_Channel3_CCR(void) { ccr_ch3[0] = phase3 - 1; ccr_ch3[1] = (phase3 + PWM_DUTY_CH3) % PWM_PERIOD; } // 设置指定通道的占空比百分比 (0-100)(选用) void Set_Channel_Duty(uint8_t channel, uint8_t duty_percent) { uint32_t duty_value = (uint32_t)((uint64_t)PWM_PERIOD * duty_percent / 100); switch (channel) { case 1: PWM_DUTY_CH1 = duty_value; Update_Channel1_CCR(); break; case 2: PWM_DUTY_CH2 = duty_value; Update_Channel2_CCR(); break; case 3: PWM_DUTY_CH3 = duty_value; Update_Channel3_CCR(); break; } } //OLED显示函数 void OLED_Show(void); /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_TIM1_Init(); MX_TIM2_Init(); MX_USART1_UART_Init(); MX_I2C2_Init(); MX_TIM5_Init(); MX_ADC1_Init(); /* USER CODE BEGIN 2 */ // 初始化ccr_ch1数组 Button_Init(); HAL_TIM_Base_Start_IT(&amp;htim2); HAL_TIM_Base_Start_IT(&amp;htim4); HAL_TIM_Base_Start_IT(&amp;htim5); phase1 = calc_phase(10); phase2 = calc_phase(130); phase3 = calc_phase(250); // 初始化ccr_ch1数组 Update_Channel1_CCR(); // 初始化ccr_ch2数组 Update_Channel2_CCR(); // 初始化ccr_ch3数组 Update_Channel3_CCR(); // HAL_TIM_OC_Start_DMA(&amp;htim1, TIM_CHANNEL_2, ccr_ch2, 2); // HAL_TIM_OC_Start_DMA(&amp;htim1, TIM_CHANNEL_3, ccr_ch3, 2); HAL_TIM_PWM_Start(&amp;htim1,TIM_CHANNEL_4); HAL_TIMEx_PWMN_Start(&amp;htim1, TIM_CHANNEL_4); HAL_TIMEx_PWMN_Start(&amp;htim1, TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(&amp;htim1, TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(&amp;htim1, TIM_CHANNEL_3); HAL_TIM_OC_Start_DMA(&amp;htim1, TIM_CHANNEL_1, ccr_ch1, 2); HAL_TIM_OC_Start_DMA(&amp;htim1, TIM_CHANNEL_2, ccr_ch2, 2); HAL_TIM_OC_Start_DMA(&amp;htim1, TIM_CHANNEL_3, ccr_ch3, 2); HAL_ADC_Start_DMA (&amp;hadc1, (uint32_t*) adc_dma_buf,sizeof(adc_dma_buf)/sizeof(uint16_t)); HAL_ADC_PollForConversion(&amp;hadc1,HAL_MAX_DELAY); filter_channel_init(&amp;filter_channel1,FILTER_MEAN,3,0); filter_channel_init(&amp;filter_channel2,FILTER_MEAN,3,0); filter_channel_init(&amp;filter_channel3,FILTER_MEAN,3,0); filter_channel_init(&amp;filter_channel4,FILTER_MEAN,3,0); HAL_Delay(20); OLED_Init(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { Button_Process(); if(flag_PWM == 1){ Settings_PWM(); flag_PWM = 0; } if(flag_OLED == 1){ OLED_Show(); flag_OLED = 0; } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 168; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&amp;RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&amp;RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ static uint8_t time2 = 0; if(htim-&gt;Instance == TIM2){ //1ms Button_Polling_1ms(); } if(htim-&gt;Instance == TIM5){ //3ms time2 = (time2 + 1) % 20; Vref = 1.2f * (4095.0f / (float)adc_dma_buf[4]); // PWM_V1 = Vref * ((float)adc_dma_buf[0] / 4095.0f); // PWM_V2 = Vref * ((float)adc_dma_buf[0] / 4095.0f); // PWM_V3 = Vref * ((float)adc_dma_buf[0] / 4095.0f); // PWM_All = Vref * ((float)adc_dma_buf[0] / 4095.0f); // 带一阶均值滤波 PWM_V1 = filter_channel_process(&amp;filter_channel1 ,(Vref * ((float)adc_dma_buf[0] / 4095.0f))); PWM_V2 = filter_channel_process(&amp;filter_channel2 ,(Vref * ((float)adc_dma_buf[1] / 4095.0f))); PWM_V3 = filter_channel_process(&amp;filter_channel3 ,(Vref * ((float)adc_dma_buf[2] / 4095.0f))); PWM_All = filter_channel_process(&amp;filter_channel4 ,(Vref * ((float)adc_dma_buf[3] / 4095.0f))); V1_Erro = fabsf(PWM_V1 - Vout_Target); V2_Erro = fabsf(PWM_V2 - Vout_Target); V3_Erro = fabsf(PWM_V3 - Vout_Target); if(time2 == 0){ flag_OLED = 1; } } if(htim-&gt;Instance == TIM4){ //5ms if(PWM_V1 &gt; Vout_Target){ // V1 &gt; Vout_Target PWM_DUTY_CH1 = V1_Erro &gt; PID_Dead_Biger ? (PWM_DUTY_CH1 + PWM_Step_long_Biger) : PWM_DUTY_CH1; //大误差调节 PWM_DUTY_CH1 = V1_Erro &gt; PID_Dead_Min ? (PWM_DUTY_CH1 + PWM_Step_long_Min) : PWM_DUTY_CH1; //小误差调节 } else{ // V1 &lt; Vout_Target PWM_DUTY_CH1 = V1_Erro &lt; PID_Dead_Biger ? (PWM_DUTY_CH1 - PWM_Step_long_Biger) : PWM_DUTY_CH1; //大误差调节 PWM_DUTY_CH1 = V1_Erro &lt; PID_Dead_Min ? (PWM_DUTY_CH1 - PWM_Step_long_Min) : PWM_DUTY_CH1; //小误差调节 } if(PWM_V2 &gt; Vout_Target){ // V2 &gt; Vout_Target PWM_DUTY_CH2 = V2_Erro &gt; PID_Dead_Biger ? (PWM_DUTY_CH2 + PWM_Step_long_Biger) : PWM_DUTY_CH2; //大误差调节 PWM_DUTY_CH2 = V2_Erro &gt; PID_Dead_Min ? (PWM_DUTY_CH2 + PWM_Step_long_Min) : PWM_DUTY_CH2; //小误差调节 } else{ // V2 &lt; Vout_Target PWM_DUTY_CH2 = V2_Erro &lt; PID_Dead_Biger ? (PWM_DUTY_CH2 + PWM_Step_long_Biger) : PWM_DUTY_CH2; //大误差调节 PWM_DUTY_CH2 = V2_Erro &lt; PID_Dead_Min ? (PWM_DUTY_CH2 + PWM_Step_long_Min) : PWM_DUTY_CH2; //小误差调节 } if(PWM_V3 &gt; Vout_Target){ // V3 &gt; Vout_Target PWM_DUTY_CH3 = V3_Erro &gt; PID_Dead_Biger ? (PWM_DUTY_CH3 + PWM_Step_long_Biger) : PWM_DUTY_CH3; //大误差调节 PWM_DUTY_CH3 = V3_Erro &gt; PID_Dead_Min ? (PWM_DUTY_CH3 + PWM_Step_long_Min) : PWM_DUTY_CH3; //小误差调节 } else{ // V3 &lt; Vout_Target PWM_DUTY_CH3 = V3_Erro &lt; PID_Dead_Biger ? (PWM_DUTY_CH3 + PWM_Step_long_Biger) : PWM_DUTY_CH3; //大误差调节 PWM_DUTY_CH3 = V3_Erro &lt; PID_Dead_Min ? (PWM_DUTY_CH3 + PWM_Step_long_Min) : PWM_DUTY_CH3; //小误差调节 } flag_PWM = 1; //启动PWM相位自调节 } } // 按键处理函数 void Button_Process(void) { int32_t result1 = Button_Take(&amp;BUT1); int32_t result2 = Button_Take(&amp;BUT2); int32_t result3 = Button_Take(&amp;BUT3); // 处理按键1 if (result1 != 0) { if (result1 == 1){ UART_Printf(&quot;按键1: 单击\n&quot;); switch(PWM_CH_Flage){ case 1: PWM_DUTY_CH1 = (PWM_DUTY_CH1 + PWM_Step_long_Biger) % (PWM_PERIOD - 1); break; case 2: PWM_DUTY_CH2 = (PWM_DUTY_CH2 + PWM_Step_long_Biger) % (PWM_PERIOD - 1); break; case 3: PWM_DUTY_CH3 = (PWM_DUTY_CH3 + PWM_Step_long_Biger) % (PWM_PERIOD - 1); break; default: break; } flag_PWM = 1; } else if (result1 == 2){ UART_Printf(&quot;按键1: 双击\n&quot;); } else if (result1 == 9){ UART_Printf(&quot;按键1: 长按触发\n&quot;); } else if (result1 &gt; 0){ // 修改长按逻辑,使其随时间增加变化速度加快 speed_factor = 1 + (result1 &gt; 100 ? (result1 / 200) : 0); UART_Printf(&quot;按键1: 长按 %dms, 速度系数: %d\n&quot;, result1, speed_factor); switch(PWM_CH_Flage){ case 1: PWM_DUTY_CH1 = (PWM_DUTY_CH1 + PWM_Step_long_Biger * speed_factor) % (PWM_PERIOD - 1); break; case 2: PWM_DUTY_CH2 = (PWM_DUTY_CH2 + PWM_Step_long_Biger * speed_factor) % (PWM_PERIOD - 1); break; case 3: PWM_DUTY_CH3 = (PWM_DUTY_CH3 + PWM_Step_long_Biger * speed_factor) % (PWM_PERIOD - 1); break; default: break; } flag_PWM = 1; } } // 处理按键2 if (result2 != 0) { if (result2 == 1){ UART_Printf(&quot;按键2: 单击\n&quot;); switch(PWM_CH_Flage){ case 1: PWM_DUTY_CH1 = (PWM_DUTY_CH1 - PWM_Step_long_Biger) % (PWM_PERIOD - 1); break; case 2: PWM_DUTY_CH2 = (PWM_DUTY_CH2 - PWM_Step_long_Biger) % (PWM_PERIOD - 1); break; case 3: PWM_DUTY_CH3 = (PWM_DUTY_CH3 - PWM_Step_long_Biger) % (PWM_PERIOD - 1); break; default: break; } flag_PWM = 1; } else if (result2 == 2){ UART_Printf(&quot;按键2: 双击\n&quot;); } else if (result2 == 9) { UART_Printf(&quot;按键2: 长按触发\n&quot;); } else if (result2 &gt; 0) { // 修改长按逻辑,使其随时间增加变化速度加快 speed_factor = 1 + (result2 &gt; 100 ? (result2 / 200) : 0); UART_Printf(&quot;按键2: 长按 %dms, 速度系数: %d\n&quot;, result2, speed_factor); switch(PWM_CH_Flage){ case 1: PWM_DUTY_CH1 = (PWM_DUTY_CH1 - PWM_Step_long_Biger * speed_factor) % (PWM_PERIOD - 1); break; case 2: PWM_DUTY_CH2 = (PWM_DUTY_CH2 - PWM_Step_long_Biger * speed_factor) % (PWM_PERIOD - 1); break; case 3: PWM_DUTY_CH3 = (PWM_DUTY_CH3 - PWM_Step_long_Biger * speed_factor) % (PWM_PERIOD - 1); break; default: break; } flag_PWM = 1; } } // 处理按键3 if (result3 != 0) { if (result3 == 1) { UART_Printf(&quot;按键3: 单击\n&quot;); PWM_CH_Flage = (PWM_CH_Flage + 1) % 4; if(PWM_CH_Flage == 0) PWM_CH_Flage = 1; } else if (result3 == 2) { UART_Printf(&quot;按键3: 双击\n&quot;); } else if (result3 == 9) { UART_Printf(&quot;按键3: 长按触发\n&quot;); } else if (result3 &gt; 0) { UART_Printf(&quot;按键3: 长按 %dms\n&quot;, result3); } } } void Settings_PWM (void){ phase1 = calc_phase(10); phase2 = calc_phase(130); phase3 = calc_phase(250); // 初始化ccr_ch1数组 Update_Channel1_CCR(); // 初始化ccr_ch2数组 Update_Channel2_CCR(); // 初始化ccr_ch3数组 Update_Channel3_CCR(); //__HAL_TIM_SET_COMPARE (&amp;htim1 ,TIM_CHANNEL_4 ,PWM_DUTY); } //OLED显示函数 void OLED_Show(void){ sprintf(message1, &quot;mode: %d&quot;, PWM_CH_Flage); sprintf(message2, &quot;PWM1: %d %.1f%%&quot;, PWM_DUTY_CH1, ((float)PWM_DUTY_CH1 / (float)PWM_PERIOD * 100)); sprintf(message3, &quot;PWM2: %d %.1f%%&quot;, PWM_DUTY_CH2, ((float)PWM_DUTY_CH2 / (float)PWM_PERIOD * 100)); sprintf(message4, &quot;PWM3: %d %.1f%%&quot;, PWM_DUTY_CH3, ((float)PWM_DUTY_CH3 / (float)PWM_PERIOD * 100)); OLED_NewFrame(); OLED_PrintString(0, 0, message1, &amp;font16x16, OLED_COLOR_NORMAL); OLED_PrintString(0, 16, message2, &amp;font16x16, OLED_COLOR_NORMAL); OLED_PrintString(0, 32, message3, &amp;font16x16, OLED_COLOR_NORMAL); OLED_PrintString(0, 48, message4, &amp;font16x16, OLED_COLOR_NORMAL); OLED_ShowFrame(); } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf(&quot;Wrong parameters value: file %s on line %d\r\n&quot;, file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ 评价一下
最新发布
11-06
extern ERROR_REG1 error_reg1; typedef union{ struct{ Uint16 ipmFault :1; //母线硬件过流 Uint16 overVolt :1; //母线直流过压 Uint16 lackVolt :1; //母线直流欠压 Uint16 dbFault :1; //制动故障 Uint16 overCrt :1; //电机过流 Uint16 overLoad :1; //电机过载保护 Uint16 blockProtect :1; //堵转保护 Uint16 reEntrance :1; //软件重入softFault1 软件故障 Uint16 eeprom :1; //数据保存错误 Uint16 unInitEeprom :1; //未恢复出厂设置 Uint16 senserAerr :1; //A相电流采样错误 Uint16 senserBerr :1; //B相电流采样错误 Uint16 mtOverTemp :1; //暂未使用 预留44 Uint16 mdOverTemp :1; //驱动器过温 Uint16 hdPhaseOverCurrent :1; //硬件相电流过流 Uint16 mtTypeChange :1; //更换电机型号,请重启 }bits; Uint16 word; }ERROR_REG1; /* ============================================================================== System Name: MAIN.C File Name: MAIN.C Description: Primary system file for the Real Implementation of Position Control Based Sensored Field Orientation Control for a Three Phase Permanent- Magnet Synchronous Motor (PMSM) using QEP sensor Originator: Motor control systems Group Note: ===================================================================================== History: ------------------------------------------------------------------------------------- 04-01-2009 Version 1.00: Support both F280x and F281x targets ================================================================================= */ #ifndef MAIN_C #define MAIN_C #include &quot;pmsmahf.h&quot; void main(void) { fun_sysInit(); for(;;) { fun_MODBUS_Idle(); if(1 == mtoffsetTest_offsetTestOkSaveFlag) { fun_saveData_SetChangFlag((int16*)&amp;mt_eangleOffset); mtoffsetTest_offsetTestOkSaveFlag = 0; } } } interrupt void MainISR(void) { fun_ad_triger(); ServiceDog(); EALLOW; // Enable EALLOW EPwm1Regs.ETCLR.bit.INT = 1; // Enable more interrupts EDIS; // Disable EALLOW // ------------------------------------------------------------------------------ // Acknowledge interrupt to recieve more interrupts from PIE group 2 // ------------------------------------------------------------------------------ PieCtrlRegs.PIEACK.all |= PIEACK_GROUP3; // ------------------------------------------------------------------------------ // Call the mtAngleOrigin function. // ------------------------------------------------------------------------------ debug_AD_RESULT9 = error_reg2.word + error_reg1.word; fun_mtAngleOrigin(); // ------------------------------------------------------------------------------ // Call the motorDrive function. // ------------------------------------------------------------------------------ fun_motorDrive(); // ------------------------------------------------------------------------------ // Call the mtAngleOrigin function. // ------------------------------------------------------------------------------ fun_mtAngleOrigin_getMaxIn(); // ------------------------------------------------------------------------------ // 制动控制 // ------------------------------------------------------------------------------ fun_dbCtrl(); // ------------------------------------------------------------------------------ // Call the timerRt update function. // ------------------------------------------------------------------------------ fun_rtTaskTimerUpdate(); // ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------ fun_refreshFbk_fast(); // ------------------------------------------------------------------------------ // 缺相检测 // ------------------------------------------------------------------------------ fun_phaseLack(); // ------------------------------------------------------------------------------ // Call the DATALOG update function. // ------------------------------------------------------------------------------ fun_dataLog(); // ------------------------------------------------------------------------------ IER |= (M_INT3); //set IER.bit3 // Enable global Interrupts and higher priority real-time debug events: EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM // ------------------------------------------------------------------------------ // Call the rtSchedule function. // ------------------------------------------------------------------------------ fun_scheduleRt(); } interrupt void PdpintISR() { #if HD_PHASE_OC_SOURCE==HD_PHASE_OC_HARDWARE DINT; EPwm1Regs.TZCLR.bit.INT = 1; // Enable more interrupts if(0 == GpioDataRegs.GPADAT.bit.GPIO12) //TZ1//注意:有时候电平时间过短,可能采集不到 { error_reg1.bits.hdPhaseOverCurrent = 1; } else { error_reg1.bits.ipmFault = 1; } // drv1.EnableFlag = 0; // drv1.update(&amp;drv1); // Acknowledge interrupt to recieve more interrupts from PIE group 1 PieCtrlRegs.PIEACK.all |= PIEACK_GROUP1; // Enable global Interrupts and higher priority real-time debug events: EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM #endif } #endif //=========================================================================== // No more. //=========================================================================== /*===================================================================================== File name: overLoad.c Originator: Motor Control Systems Group Description: ===================================================================================== History: ------------------------------------------------------------------------------------- 04-15-2005 Version 3.20 -------------------------------------------------------------------------------------*/ #ifndef _OVERLOAD_C #define _OVERLOAD_C #include &quot;pmsmahf.h&quot; /*=====================================================================================*/ /**/ /*=====================================================================================*/ void fun_overLoadInit() { overLoad_Is_Fbk = 0; overLoad_counter = 0; overCurrentCount = 0; block_counter = 0; mtEncErr_counter = 0; overLoad_coefOne = _IQ(1.0); overLoad_coefOverRate = _IQ(1.05); } /*=====================================================================================*/ /*1ms*///过载报警 /*=====================================================================================*/ void fun_overLoad(void) { if(IQ_CrtOvLoad_limt &lt; IQ_CrtLimt) { overLoad_Crt2 = IQ_CrtOvLoad_limt; } else { overLoad_Crt2 = IQ_CrtLimt; //IQ_TrqOvLoadCrt2; } if(MOTOR_TYPE_DM3710OZ == mt_type) overLoad_Crt1 = IQ_CrtOvLoad*2; //1/1 //_IQmpy(IQ_EM_PHCurrent_Rated,overLoad_coefOverRate);//Q_TrqOvLoadCrt1; else overLoad_Crt1 = IQ_CrtOvLoad; //overLoad_Time2 = CrtOvLoadTime2;//s if(CrtOvLoadTime2 &gt; 0) { overLoad_delta2 = overLoad_coefOne/CrtOvLoadTime2/1000; } else { overLoad_delta2 = overLoad_coefOne; } if(overLoad_delta2 == 0) { overLoad_delta2 = 1; } if(CrtOvLoadTime1 &gt; 0) { overLoad_delta1 = overLoad_coefOne/CrtOvLoadTime1/1000; } else { overLoad_delta1 = overLoad_coefOne; } if(overLoad_delta1 == 0) { overLoad_delta1 = 1; } //over load // overLoad_tmp2 = _IQmag(park1.Ds,park1.Qs); overLoad_tmp2 = overLoad_Is_Fbk; // tmp1 = overLoad_Crt2; if(overLoad_tmp2 &gt; overLoad_Crt2) { overLoad_tmp2 = overLoad_Crt2; } if(overLoad_tmp2 - overLoad_Crt1 &gt; 0) { overLoad_tmp1 = _IQdiv((overLoad_tmp2 - overLoad_Crt1),(overLoad_Crt2 - overLoad_Crt1)); overLoad_delta = overLoad_delta1 + _IQmpy(overLoad_tmp1,(overLoad_delta2 - overLoad_delta1)); if(overLoad_counter &gt; _IQ(1)) { error_reg1.bits.overLoad = 1; } else { overLoad_counter += overLoad_delta; } } else { if(overLoad_counter &gt; 0) { if(MOTOR_TYPE_DM3710OZ == mt_type) overLoad_counter -= 32*overLoad_delta1; //16 else overLoad_counter -= 16*overLoad_delta1; //16 } else { overLoad_counter = 0; } } } /*=====================================================================================*/ /*375us*/ //过流报警 /*=====================================================================================*/ void fun_overCurrent(void) { overLoad_Is_Fbk = _IQmag(park1.Ds,park1.Qs); //over current if(IGBT_type == 0) { if(overLoad_Is_Fbk &gt; IQ_CrtLeak) { if(overCurrentCount &lt; 3) { overCurrentCount++; } else { error_reg1.bits.overCrt = 1; overCurrentCount = 0; } } else { overCurrentCount = 0; } } else { if(overLoad_Is_Fbk &gt; (IQ_CrtLeak + IQ_CrtLeak/3)) { if(overCurrentCount &lt; 3) { overCurrentCount++; } else { error_reg1.bits.overCrt = 1; overCurrentCount = 0; } } else { overCurrentCount = 0; } } } /*=====================================================================================*/ /*125us*/ //相电流报警 /*=====================================================================================*/ void fun_phaseCurrent(void) { if((labs(adc_allMeas.ImeasA) &gt; CrtPhase) || (labs(adc_allMeas.ImeasB) &gt; CrtPhase) || (labs(adc_allMeas.ImeasC) &gt; CrtPhase)) { error_reg1.bits.hdPhaseOverCurrent = 1; } } /*=====================================================================================*/ /*1ms*///堵转报警 /*=====================================================================================*/ void fun_blockProtect(void) { blockProtect_time = CrtBlockTime*1000;//ms //_IQ(0.02);//600*0.02 if((0 == speed_qep.Speed) &amp;&amp; (overLoad_Is_Fbk &gt; IQ_CrtBlockCrt)) { if(block_counter &gt; blockProtect_time)//ms { error_reg1.bits.blockProtect = 1; } else { block_counter++; } } else { block_counter = 0; } } /*=====================================================================================*/ /*1ms*///监测编码器异常 /*=====================================================================================*/ void fun_mtEncErr(void) { if(appCtrl_trqInitFlag == 3 &amp;&amp; runEnable == 1 &amp;&amp; mtCtrl_fsm_statue == MTCTRL_STOP &amp;&amp; functionStatue == SYSCTRLMOD_RELEASED) //停机状态 { if((labs(adc_allMeas.ImeasA) &lt; CrtEncErr) &amp;&amp; (labs(adc_allMeas.ImeasB) &lt; CrtEncErr) &amp;&amp; (labs(adc_allMeas.ImeasC) &lt; CrtEncErr)) { mtEncErr_counter = 0; } else { mtEncErr_counter += labs(adc_allMeas.ImeasA)/CrtEncErr; //100A/39A=2 mtEncErr_counter += labs(adc_allMeas.ImeasB)/CrtEncErr; mtEncErr_counter += labs(adc_allMeas.ImeasC)/CrtEncErr; } if(mtEncErr_counter &gt; 20) { #if HD_PHASE_OC_SOURCE == HD_PHASE_OC_SOFTWARE error_reg1.bits.ipmFault = 1; #else error_reg2.bits.mtEnc_zero = 1; #endif mt_eangleOffset = 0; mtoffsetTest_offsetTestOkSaveFlag = 1; } } else { mtEncErr_counter = 0; } } #endif 分析上述代码,分析什么条件下error_reg1.bits.ipmFault = 1
07-19
在DC-AC单相全桥逆变电路中,使用stm32f103RCT6(DMA没有自带双缓冲模式?),软件部分,SPWM.c中我采用外部程序生成正弦表的1600个数据点,(由于是中央对齐模式2,使用CC1触发DMA,故每个TIM1周期更新两个CCR数据值,那么一个正弦波周期就是800个数据点)通过TIM1的中央对齐模式2(ARR=1800-1,PSC=1-1,时序:0--&gt;ARR--&gt;0),每个TIM1周期为50us,每个TIM1周期更新两次CCR(向上计数时CNT=CCR_A和向下计数CNT=CCR_B时),使用TIM1_CC1触发DMA1的通道二将正弦表中的数据依次搬运到TIM1_CCR1中完成SPWM的生成,我只需要用到一路主路PWM和互补PWM(即CH1和CH1N,因为我使用的驱动使IR2104,它只有一个输入端IN,两片IR2104,一片输入CH1另一片输入CH1N,它就是这么使用的)。ADC.c中打算采用TIM1_CC2触发ADC(同样是每个TIM1周期会采到两个样点,因为时序:0--&gt;ARR--&gt;0过程中会触发两次CC2)(双ADC同步规则分别采电压和电流)+DMA搬运进uint32_t数组ADC_Dual_Value[Buffersize]中(这里Buffersize为1600,前800个数据点是采到的一个完整正弦周期的数据点,后800个点也是采到的完整的正弦周期的数据点,我打算使用滑动窗口计算Rms而不是等待采完一整个正弦周期20ms才能计算一次Rms送入pid,由于数据量太大,每个周期虽然实际采了800个点,但是我实际只取100个点(800个点里每8个数据取1个),但是我一旦在TIM3触发的定时中断里执行Control_Loop()时,OLED就会黑屏不显示(使用的0.96寸4针脚(VCC、GND、SCL(PB8)、SDA(PB9))OLED显示屏,),但是注释掉TIM3_Init()时就恢复正常,应该时计算量太大了影响到OLED通信了?我该怎么办?或者换个思路使用一个定时器定时中断专门在中断里显示OLED刷新和显示的部分?代码如下,帮我分析分析,谢谢: Main.c:#include &quot;stm32f10x.h&quot; // Device header #include &quot;Delay.h&quot; #include &quot;MYDAC.h&quot; #include &quot;ADC_DMA.h&quot; #include &quot;OLED.h&quot; #include &quot;OLED_Data.h&quot; #include &quot;PID.h&quot; #include &quot;SPWM.h&quot; #include &quot;Serial.h&quot; uint8_t temp = 0; uint16_t Sam_Vol,Sam_Cur,vol_DAC; int main(void) //PA8输出主PWM PB13输出互补PWM PB0采电压 PB1采电流 { OLED_Init(); Timer3_Init(); TIM4_Init(); ADC_DMAInit(); SPWM_BDTR_Init(); //PID_Init(0.15,0.01,0,0,0,0); //Serial_DMA_Init(); OLED_ShowString(0,0,&quot;电压值:&quot;,OLED_8X16); OLED_ShowString(0,16,&quot;ADC电压:&quot;,OLED_8X16); OLED_ShowString(0,32,&quot;输出电流:&quot;,OLED_8X16); OLED_Update(); while(1) { if(Control_Flag) { Control_Loop(); Control_Flag = 0; } // Sent_Data_to_Vofa(); } } SPWM.c:#include &quot;stm32f10x.h&quot; // Device header #include &quot;Serial.h&quot; #include &quot;PID.h&quot; #include &lt;math.h&gt; #include &quot;ADC_DMA.h&quot; #include &quot;SPWM.h&quot; //DMA传输正弦表进TIM1_CCR1中的数据量 #define BufferSize_Sample 1600 // uint8_t TIM_DeadTime = 50; //待确定 //用于串口的定时中断采CCR1送入上位机,此为预备数组 //#define Sample_CCR_Num 100 //uint16_t Sample_Ready_CCR1[100];//TIM1_CCR1的采样,缓冲采样数组1,采样完毕后转移进Serial.c中的Buffer_to_Sent[]中 //uint16_t Sample_Ready_CCR2[100];//TIM1_CCR1的采样,缓冲采样数组2,采样完毕后转移进Serial.c中的Buffer_to_Sent[]中 //volatile uint16_t *Current_CCR_Buffer = Sample_Ready_CCR1; //volatile uint8_t Buffer_Ready_Flag = 0; //采满200个样点的标志位 volatile uint16_t *Current_SPWM_ReadyBuffer; //指向当前就绪SPWM缓冲区,用于更新SPWM新表 volatile uint8_t SPWM_BufferReady_Flag = 0; //SPWM缓冲区就绪标志位 volatile uint16_t* const DMA_RemainIndex = (volatile uint16_t*)(&amp;DMA1_Channel1-&gt;CNDTR); //DMA1_Channel1(搬运ADC)当前剩余数据 volatile Rms_Windows rms_windows = {0,0,0}; uint16_t DMA_CurrentIndex; //DMA1_Channel1当前索引 uint8_t Can_Get_RmsFlag = 0; //可获取有效值标志位 uint16_t SPWM_Data[BufferSize_Sample] = //SPWM的CCR值,大缓冲数组,每800个点为一个正弦周期(20ms),每个TIM1周期更新两个点 { 900,906,912,918,925,931,937,943,950,956,962,969,975,981,987,994, 1000,1006,1012,1018,1025,1031,1037,1043,1049,1056,1062,1068,1074,1080,1086,1092, 1098,1105,1111,1117,1123,1129,1135,1141,1147,1153,1159,1165,1170,1176,1182,1188, 1194,1200,1206,1211,1217,1223,1229,1234,1240,1246,1251,1257,1263,1268,1274,1279, 1285,1290,1296,1301,1307,1312,1317,1323,1328,1333,1339,1344,1349,1354,1360,1365, 1370,1375,1380,1385,1390,1395,1400,1405,1409,1414,1419,1424,1429,1433,1438,1443, 1447,1452,1456,1461,1465,1470,1474,1478,1483,1487,1491,1495,1500,1504,1508,1512, 1516,1520,1524,1528,1532,1535,1539,1543,1547,1550,1554,1558,1561,1565,1568,1572, 1575,1578,1582,1585,1588,1591,1594,1597,1601,1604,1607,1609,1612,1615,1618,1621, 1623,1626,1629,1631,1634,1636,1639,1641,1643,1646,1648,1650,1652,1654,1656,1658, 1660,1662,1664,1666,1668,1669,1671,1673,1674,1676,1677,1679,1680,1682,1683,1684, 1685,1686,1688,1689,1690,1691,1692,1692,1693,1694,1695,1695,1696,1697,1697,1698, 1698,1698,1699,1699,1699,1699,1699,1699,1700,1699,1699,1699,1699,1699,1699,1698, 1698,1698,1697,1697,1696,1695,1695,1694,1693,1692,1692,1691,1690,1689,1688,1686, 1685,1684,1683,1682,1680,1679,1677,1676,1674,1673,1671,1669,1668,1666,1664,1662, 1660,1658,1656,1654,1652,1650,1648,1646,1643,1641,1639,1636,1634,1631,1629,1626, 1623,1621,1618,1615,1612,1609,1607,1604,1601,1597,1594,1591,1588,1585,1582,1578, 1575,1572,1568,1565,1561,1558,1554,1550,1547,1543,1539,1535,1532,1528,1524,1520, 1516,1512,1508,1504,1500,1495,1491,1487,1483,1478,1474,1470,1465,1461,1456,1452, 1447,1443,1438,1433,1429,1424,1419,1414,1409,1405,1400,1395,1390,1385,1380,1375, 1370,1365,1360,1354,1349,1344,1339,1333,1328,1323,1317,1312,1307,1301,1296,1290, 1285,1279,1274,1268,1263,1257,1251,1246,1240,1234,1229,1223,1217,1211,1206,1200, 1194,1188,1182,1176,1170,1165,1159,1153,1147,1141,1135,1129,1123,1117,1111,1105, 1098,1092,1086,1080,1074,1068,1062,1056,1049,1043,1037,1031,1025,1018,1012,1006, 1000,994,987,981,975,969,962,956,950,943,937,931,925,918,912,906, 900,893,887,881,874,868,862,856,849,843,837,830,824,818,812,805, 799,793,787,781,774,768,762,756,750,743,737,731,725,719,713,707, 701,694,688,682,676,670,664,658,652,646,640,634,629,623,617,611, 605,599,593,588,582,576,570,565,559,553,548,542,536,531,525,520, 514,509,503,498,492,487,482,476,471,466,460,455,450,445,439,434, 429,424,419,414,409,404,399,394,390,385,380,375,370,366,361,356, 352,347,343,338,334,329,325,321,316,312,308,304,299,295,291,287, 283,279,275,271,267,264,260,256,252,249,245,241,238,234,231,227, 224,221,217,214,211,208,205,202,198,195,192,190,187,184,181,178, 176,173,170,168,165,163,160,158,156,153,151,149,147,145,143,141, 139,137,135,133,131,130,128,126,125,123,122,120,119,117,116,115, 114,113,111,110,109,108,107,107,106,105,104,104,103,102,102,101, 101,101,100,100,100,100,100,100,100,100,100,100,100,100,100,101, 101,101,102,102,103,104,104,105,106,107,107,108,109,110,111,113, 114,115,116,117,119,120,122,123,125,126,128,130,131,133,135,137, 139,141,143,145,147,149,151,153,156,158,160,163,165,168,170,173, 176,178,181,184,187,190,192,195,198,202,205,208,211,214,217,221, 224,227,231,234,238,241,245,249,252,256,260,264,267,271,275,279, 283,287,291,295,299,304,308,312,316,321,325,329,334,338,343,347, 352,356,361,366,370,375,380,385,390,394,399,404,409,414,419,424, 429,434,439,445,450,455,460,466,471,476,482,487,492,498,503,509, 514,520,525,531,536,542,548,553,559,565,570,576,582,588,593,599, 605,611,617,623,629,634,640,646,652,658,664,670,676,682,688,694, 701,707,713,719,725,731,737,743,750,756,762,768,774,781,787,793, 799,805,812,818,824,830,837,843,849,856,862,868,874,881,887,893, 900,906,912,918,925,931,937,943,950,956,962,969,975,981,987,994, 1000,1006,1012,1018,1025,1031,1037,1043,1049,1056,1062,1068,1074,1080,1086,1092, 1098,1105,1111,1117,1123,1129,1135,1141,1147,1153,1159,1165,1170,1176,1182,1188, 1194,1200,1206,1211,1217,1223,1229,1234,1240,1246,1251,1257,1263,1268,1274,1279, 1285,1290,1296,1301,1307,1312,1317,1323,1328,1333,1339,1344,1349,1354,1360,1365, 1370,1375,1380,1385,1390,1395,1400,1405,1409,1414,1419,1424,1429,1433,1438,1443, 1447,1452,1456,1461,1465,1470,1474,1478,1483,1487,1491,1495,1500,1504,1508,1512, 1516,1520,1524,1528,1532,1535,1539,1543,1547,1550,1554,1558,1561,1565,1568,1572, 1575,1578,1582,1585,1588,1591,1594,1597,1601,1604,1607,1609,1612,1615,1618,1621, 1623,1626,1629,1631,1634,1636,1639,1641,1643,1646,1648,1650,1652,1654,1656,1658, 1660,1662,1664,1666,1668,1669,1671,1673,1674,1676,1677,1679,1680,1682,1683,1684, 1685,1686,1688,1689,1690,1691,1692,1692,1693,1694,1695,1695,1696,1697,1697,1698, 1698,1698,1699,1699,1699,1699,1699,1699,1700,1699,1699,1699,1699,1699,1699,1698, 1698,1698,1697,1697,1696,1695,1695,1694,1693,1692,1692,1691,1690,1689,1688,1686, 1685,1684,1683,1682,1680,1679,1677,1676,1674,1673,1671,1669,1668,1666,1664,1662, 1660,1658,1656,1654,1652,1650,1648,1646,1643,1641,1639,1636,1634,1631,1629,1626, 1623,1621,1618,1615,1612,1609,1607,1604,1601,1597,1594,1591,1588,1585,1582,1578, 1575,1572,1568,1565,1561,1558,1554,1550,1547,1543,1539,1535,1532,1528,1524,1520, 1516,1512,1508,1504,1500,1495,1491,1487,1483,1478,1474,1470,1465,1461,1456,1452, 1447,1443,1438,1433,1429,1424,1419,1414,1409,1405,1400,1395,1390,1385,1380,1375, 1370,1365,1360,1354,1349,1344,1339,1333,1328,1323,1317,1312,1307,1301,1296,1290, 1285,1279,1274,1268,1263,1257,1251,1246,1240,1234,1229,1223,1217,1211,1206,1200, 1194,1188,1182,1176,1170,1165,1159,1153,1147,1141,1135,1129,1123,1117,1111,1105, 1098,1092,1086,1080,1074,1068,1062,1056,1049,1043,1037,1031,1025,1018,1012,1006, 1000,994,987,981,975,969,962,956,950,943,937,931,925,918,912,906, 900,893,887,881,874,868,862,856,849,843,837,830,824,818,812,805, 799,793,787,781,774,768,762,756,750,743,737,731,725,719,713,707, 701,694,688,682,676,670,664,658,652,646,640,634,629,623,617,611, 605,599,593,588,582,576,570,565,559,553,548,542,536,531,525,520, 514,509,503,498,492,487,482,476,471,466,460,455,450,445,439,434, 429,424,419,414,409,404,399,394,390,385,380,375,370,366,361,356, 352,347,343,338,334,329,325,321,316,312,308,304,299,295,291,287, 283,279,275,271,267,264,260,256,252,249,245,241,238,234,231,227, 224,221,217,214,211,208,205,202,198,195,192,190,187,184,181,178, 176,173,170,168,165,163,160,158,156,153,151,149,147,145,143,141, 139,137,135,133,131,130,128,126,125,123,122,120,119,117,116,115, 114,113,111,110,109,108,107,107,106,105,104,104,103,102,102,101, 101,101,100,100,100,100,100,100,100,100,100,100,100,100,100,101, 101,101,102,102,103,104,104,105,106,107,107,108,109,110,111,113, 114,115,116,117,119,120,122,123,125,126,128,130,131,133,135,137, 139,141,143,145,147,149,151,153,156,158,160,163,165,168,170,173, 176,178,181,184,187,190,192,195,198,202,205,208,211,214,217,221, 224,227,231,234,238,241,245,249,252,256,260,264,267,271,275,279, 283,287,291,295,299,304,308,312,316,321,325,329,334,338,343,347, 352,356,361,366,370,375,380,385,390,394,399,404,409,414,419,424, 429,434,439,445,450,455,460,466,471,476,482,487,492,498,503,509, 514,520,525,531,536,542,548,553,559,565,570,576,582,588,593,599, 605,611,617,623,629,634,640,646,652,658,664,670,676,682,688,694, 701,707,713,719,725,731,737,743,750,756,762,768,774,781,787,793, 799,805,812,818,824,830,837,843,849,856,862,868,874,881,887,893 }; void SPWM_BDTR_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; TIM_BDTRInitTypeDef TIM_BDTRInitStructure; DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //CH1为PA8 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&amp;GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //CH1N互补为PB13 GPIO_Init(GPIOB,&amp;GPIO_InitStructure); DMA_DeInit(DMA1_Channel2); //TIM1_CC1映射在DMA1的通道2 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&amp;TIM1 -&gt;CCR1; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPWM_Data; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = BufferSize_Sample; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel2,&amp;DMA_InitStructure); DMA_Cmd(DMA1_Channel2,ENABLE); TIM1-&gt;CCR1 = SPWM_Data[0]; //先校正第一个CCR为数组SPWM_Data[0],使得第一次CC1事件触发时DMA搬运SPWM_Data[1]进CCR1 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //中央对齐模式2,0--&gt;ARR--&gt;0的计数模式,向下计数阶段ARR--&gt;0时CNT = 0时产生更新事件 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned2; TIM_TimeBaseStructure.TIM_Period = 1800-1; //20k的频率,ARR = 3600-1 TIM_TimeBaseStructure.TIM_Prescaler = 1-1; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1,&amp;TIM_TimeBaseStructure); TIM_ClearFlag(TIM1,TIM_FLAG_CC1); //初始化前清除CC1标志位 TIM_ClearFlag(TIM2,TIM_FLAG_CC2); //初始化前清除CC2标志位 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //主路 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //互补路 TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; TIM_OC1Init(TIM1,&amp;TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //主路 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //互补路 TIM_OCInitStructure.TIM_Pulse = 300; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; TIM_OC2Init(TIM1,&amp;TIM_OCInitStructure); TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; TIM_BDTRInitStructure.TIM_DeadTime = TIM_DeadTime; TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable; //先不使用刹车 TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; //刹车触发极性,低电平 TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable; //故障后不自动恢复输出,需自行手动恢复 TIM_BDTRConfig(TIM1,&amp;TIM_BDTRInitStructure); // NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; //0 0 // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&amp;NVIC_InitStructure); // TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&amp;NVIC_InitStructure); DMA_ITConfig(DMA1_Channel2, DMA_IT_TC | DMA_IT_HT, ENABLE); NVIC_EnableIRQ(DMA1_Channel2_IRQn); // 启用DMA中断通道2 TIM_DMACmd(TIM1,TIM_DMA_CC1,ENABLE); //TIM1的CC1事件更新时触发DMA TIM_ARRPreloadConfig(TIM1,ENABLE); //预装载ARR TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable); //预装载 TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_OC2Ref); //TIM1_CC2触发ADC TIM_CtrlPWMOutputs(TIM1,ENABLE); //使能输出主PWM TIM_Cmd(TIM1,ENABLE); } void PWM_SetCCR(TIM_TypeDef* TIMx,uint8_t CHx,uint16_t Compare,uint16_t Upper_LimitCCR) //占空比设置 { if(CHx&lt;1||CHx&gt;4) return; if(Compare &gt; Upper_LimitCCR) Compare = Upper_LimitCCR; switch (CHx) { case 1:TIM_SetCompare1(TIMx,Compare);break; case 2:TIM_SetCompare2(TIMx,Compare);break; case 3:TIM_SetCompare3(TIMx,Compare);break; case 4:TIM_SetCompare4(TIMx,Compare);break; } } uint16_t PWM_GetCCR(TIM_TypeDef* TIMx,uint8_t CHx) //参数1:定时器TIMX 参数2:通道,可为1~4 { if(CHx&lt;1||CHx&gt;4) return 0; uint16_t CCR; switch (CHx) { case 1:CCR =TIM_GetCapture1(TIMx);break; case 2:CCR =TIM_GetCapture2(TIMx);break; case 3:CCR =TIM_GetCapture3(TIMx);break; case 4:CCR =TIM_GetCapture4(TIMx);break; } return CCR; } void SPWM_Update(float Gain,volatile uint16_t *Ready_Buffer) //正弦表更新,传入Current_SPWM_ReadyBuffer指向待写入的缓冲区 { static float last_Gain = 1.0f; int Offset_Val,New_Val; if(SPWM_BufferReady_Flag&amp;&amp;fabs(Gain - last_Gain)&gt;0.005f) { SPWM_BufferReady_Flag = 0; for(uint16_t i=0;i&lt;800;i++ ) { Offset_Val = (int16_t)(Ready_Buffer[i] -900); New_Val = (int16_t)((Offset_Val * Gain) + 900); if(New_Val &lt; 60) New_Val = 60; else if(New_Val &gt; 1740) New_Val = 1740; Ready_Buffer[i] = (uint16_t)New_Val; } last_Gain = Gain; } } void Rms_WindowsInit(void) { rms_windows.Volt_SquareSum = 0; rms_windows.Cur_SquareSum = 0; rms_windows.Count = 0; } void Rms_WindowsUpdate(void) { uint16_t DMA_Remain = *DMA_RemainIndex; //DMA传输剩余数据量 DMA_CurrentIndex = ADC_DMA_BufferSize - DMA_Remain; //DMA当前索引 //需移除点的索引,一个正弦周期(20ms)共采800个点,每8个点取一个点,实际一共仅取100个采样点 uint16_t Old_Index = (DMA_CurrentIndex - DMA_CurrentIndex%8 + ADC_DMA_BufferSize - ADC_BufferSize)%ADC_DMA_BufferSize; uint16_t New_Index = DMA_CurrentIndex - DMA_CurrentIndex%8; uint32_t Old_Value = ADC_Dual_Value[Old_Index]; //需移除的点的32位值 uint32_t New_Value = ADC_Dual_Value[New_Index]; //解析需移除的点的值为高16位的电流值和低16位的电压值 uint16_t New_Volt = New_Value &amp; 0xFFFF; uint16_t New_Cur = New_Value &gt;&gt; 16; uint16_t Old_Volt = Old_Value &amp; 0xFFFF; uint16_t Old_Cur = Old_Value &gt;&gt; 16; //更新新的平方和 rms_windows.Volt_SquareSum += (New_Volt * New_Volt - Old_Volt * Old_Volt); rms_windows.Cur_SquareSum += (New_Cur * New_Cur - Old_Cur * Old_Cur); } float Get_Volt_RmsValue(void) { if(Can_Get_RmsFlag) { return sqrtf((float)rms_windows.Volt_SquareSum / ADC_BufferSize *3.3f/4095.0f); } else return 0; } float Get_Cur_RmsValue(void) { if(Can_Get_RmsFlag) { return sqrtf((float)rms_windows.Cur_SquareSum / ADC_BufferSize *3.3f/4095.0f); } else return 0; } void DMA1_Channel2_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_HT2)) //上半缓冲传输完成,上次的表已经传输完了,该传输上次表传输完成之前PID已生成好的新表了 { SPWM_BufferReady_Flag = 1; //置上半缓冲就绪1,该传输下半缓冲区了 Current_SPWM_ReadyBuffer = SPWM_Data; //当前源地址的指针指向下半缓冲区,将上次PID已更新好的数据写入TIM1_CC1 DMA_ClearITPendingBit(DMA1_IT_HT2); } if(DMA_GetITStatus(DMA1_IT_TC2)) //下半缓冲完成,上次的表已经传输完了,该传输上次表传输完成之前PID已生成好的新表了 { SPWM_BufferReady_Flag = 2; //置下半缓冲就绪2,该传输上半缓冲区了 Current_SPWM_ReadyBuffer = SPWM_Data+ 800; //当前源地址的指针指向上半缓冲区,将上次PID已更新好的数据写入TIM1_CC1 DMA_ClearITPendingBit(DMA1_IT_TC2); } } //void TIM1_UP_IRQHandler(void) //{ //// static uint8_t TIM_Count_Sample_CCR = 0; //// static uint8_t Sample_Num = 0; // if(TIM_GetITStatus(TIM1,TIM_IT_Update)) // { // // ADC_SoftwareStartConvCmd(ADC1,ENABLE); //每个TIM1中断软件触发ADC采样 // Window_UpdateFlag = 1; // // TIM_ClearITPendingBit(TIM1, TIM_IT_Update); // // // //if(++cycle_count &gt;= 16000) //16000个TIM1中断时复位DMA // // { // // DMA_Cmd(DMA1_Channel2, DISABLE); //先关闭才能配置DMA // // DMA1_Channel2-&gt;CNDTR = BufferSize_Sample; // // DMA1_Channel2-&gt;CMAR = (uint32_t)SPWM_Data; // // TIM1-&gt;CCR1 = SPWM_Data[0]; //校正第一个CCR为数组SPWM_Data[0],使得第一次CC1事件触发时DMA搬运SPWM_Data[1]进CCR1 // // DMA_Cmd(DMA1_Channel2, ENABLE); // // cycle_count = 0; // // } // // // //// if(++TIM_Count_Sample_CCR &gt;= 40) //每40次定时中断(0.2ms)就采一次CCR1进数组Sample_CCR【】中 //// { //// TIM_Count_Sample_CCR = 0; ////__disable_irq(); //原子保护,禁止中断 //// if(Sample_Num &lt; Sample_CCR_Num) //如果数组没填满到Sample_CCR_Num这个次数,那就将CCR1存进去 //// { //// Current_CCR_Buffer[Sample_Num] = TIM1-&gt;CCR1; //// Sample_Num++; //// } ////__enable_irq(); //原子保护恢复,允许中断 //// if(Sample_Num &gt;= Sample_CCR_Num) //如果数组已经采满Sample_CCR_Num这个次数,就产生标志位 //// { ////__disable_irq(); //原子保护,禁止中断 //// if(Current_CCR_Buffer == Sample_Ready_CCR1) //寻找当前指向哪个缓冲区 //// { //// Current_CCR_Buffer = Sample_Ready_CCR2; //缓冲区1满,切换缓冲区2 //// Buffer_Ready_Flag = 1; //标志位置1 //// } //// else //// { //// Current_CCR_Buffer = Sample_Ready_CCR1; //缓冲区2满,切换缓冲区1 //// Buffer_Ready_Flag = 2; //标志位置2 //// } //// Sample_Num = 0; //将Sample_Num复位 ////__enable_irq(); //原子保护恢复,允许中断 //// //// } //// } // // } // //} // // // // ADC_DMA.c:#include &quot;stm32f10x.h&quot; #include &quot;PID.h&quot; #include &quot;Delay.h&quot; #include &quot;ADC_DMA.h&quot; #include &quot;SPWM.h&quot; #include &quot;OLED.h&quot; #include &quot;OLED_Data.h&quot; #include&lt;math.h&gt; #define ChannelNum 1 uint32_t ADC_Dual_Value[ADC_DMA_BufferSize]; //使用双ADC规则同步 32位的ADC1_DR存数据,低16位为ADC116位为ADC2 uint16_t Volt_Value[SimplifyADC_BufferSize]; uint16_t Cur_Value[SimplifyADC_BufferSize]; float Void_Gain = 11; float Cur_Gain = 1.47205; volatile uint8_t ADC_DMA_CompleteFlag = 0; // DMA缓冲区就绪标志 volatile uint32_t *Current_ADC_Buffer; //指向当前就绪缓冲区 void TIM2_PWM_Init(void) //TIM2的通道1产生的PWM用于开关,通道2产生的PWM用于触发ADC采样 { // 时基参数配置(产生100kHz PWM) TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0输出PWM用于开关 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &amp;GPIO_InitStructure); // 定时器配置 TIM_TimeBaseStructure.TIM_Period = 1000-1; // ARR = 1000 TIM_TimeBaseStructure.TIM_Prescaler = 8-1; // PSC = 71 TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &amp;TIM_TimeBaseStructure); // PWM通道2配置(PA1)用于触发ADC TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 时序:---------_____(采样)_____ TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 300; // 75%占空比时采样(此处处于mos关断中间时刻) TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC2Init(TIM2, &amp;TIM_OCInitStructure); // 配置定时器触发输出 // TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_OC2Ref); // TIM_CtrlPWMOutputs(TIM2, ENABLE); // TIM_Cmd(TIM2, ENABLE); // 启动定时器 } void TIM4_Init(void) //用于中断刷新OLED { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); // 时基参数配置 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; // 定时器配置 TIM_TimeBaseStructure.TIM_Period = 10000-1; // ARR TIM_TimeBaseStructure.TIM_Prescaler = 720-1; // PSC TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM4, &amp;TIM_TimeBaseStructure); TIM_InternalClockConfig(TIM4); NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&amp;NVIC_InitStructure); TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); TIM_Cmd(TIM4, ENABLE); // 启动定时器 } void ADC_DMA_Init(void) //双ADC规则同步采样,PB0采电压,PB1采电流 { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA1_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; // 使能时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_ADC1| RCC_APB2Periph_ADC2, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 配置PB0(ADC1通道8)采电压、PB1(ADC1通道9)采电流为模拟输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOB, &amp;GPIO_InitStructure); // DMA配置 DMA_DeInit(DMA1_Channel1); DMA1_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&amp;ADC1-&gt;DR; DMA1_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_Dual_Value; //ADC_DMA_BufferSize个数据的大缓冲数组 DMA1_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA1_InitStructure.DMA_BufferSize = ADC_DMA_BufferSize; DMA1_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA1_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA1_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; DMA1_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; DMA1_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA1_InitStructure.DMA_Priority = DMA_Priority_High; DMA1_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &amp;DMA1_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE); //配置ADC1,主ADC ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 启用扫描模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC2; //使用T1_CC2触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &amp;ADC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&amp;NVIC_InitStructure); DMA_ITConfig(DMA1_Channel1, DMA_IT_TC | DMA_IT_HT, ENABLE); NVIC_EnableIRQ(DMA1_Channel1_IRQn); // 启用DMA中断通道1 ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5); // 配置通道顺序(通道8) PB0对应序列1采电压 ADC_DMACmd(ADC1, ENABLE); //配置ADC2,从ADC,配置与ADC1相同 ADC_Init(ADC2, &amp;ADC_InitStructure); ADC_RegularChannelConfig(ADC2, ADC_Channel_9, 1, ADC_SampleTime_55Cycles5); //// 配置通道顺序(通道9) PB1对应序列1采电流 //操作ADC1_CR1寄存器之前先关闭ADC1和ADC2 ADC_Cmd(ADC1, DISABLE); ADC_Cmd(ADC2, DISABLE); //操作ADC1_CR1的位19:16位[3:0] = 0110 为规则同步模式 uint32_t tmp = ADC1-&gt;CR1; tmp &amp;= 0xFFF0FFFF; tmp |= 0x00060000; ADC1-&gt;CR1 = tmp; // 先ADC2校准 ADC_Cmd(ADC2, ENABLE); Delay_us(1); ADC_ResetCalibration(ADC2); while(ADC_GetResetCalibrationStatus(ADC2)); ADC_StartCalibration(ADC2); while(ADC_GetCalibrationStatus(ADC2)); // ADC1校准 ADC_Cmd(ADC1, ENABLE); Delay_us(1); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); // 启用外部触发 ADC_ExternalTrigConvCmd(ADC1, ENABLE); ADC_ExternalTrigConvCmd(ADC2, ENABLE); } void ADC_DMAInit(void) { // TIM2_PWM_Init(); //全桥不需TIM2_CC2触发ADC采样,需要TIM1_CC1触发ADC ADC_DMA_Init(); } void Get_ADC_Value(volatile uint32_t *ADC_Value) //解析32位采样数据,暂不用 { for(int i=0;i&lt;ADC_BufferSize;i++) { Volt_Value[i] = ADC_Value[i] &amp; 0xFFFF; Cur_Value[i] = ADC_Value[i] &gt;&gt;16; } } void DMA1_Channel1_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_HT1)) //DMA半传输完成标志位 { Can_Get_RmsFlag = 1; //标记前半缓冲区就绪,前400个数据已就绪,可以调用float Get_Volt_RmsValue()和float Get_Cur_RmsValue(); //ADC_DMA_CompleteFlag = 1; // 标记前半缓冲区就绪,前400个数据已就绪 // Current_ADC_Buffer = &amp;ADC_Dual_Value[0]; //指针指向缓冲区【0】 DMA_ITConfig(DMA1_Channel1, DMA_IT_TC | DMA_IT_HT, DISABLE); //第一次采满一个周期就关闭中断,此后方可调用float Get_Volt_RmsValue()和float Get_Cur_RmsValue(); DMA_ClearITPendingBit(DMA1_IT_HT1); } //if(DMA_GetITStatus(DMA1_IT_TC1)) //DMA全部传输完成标志位 //{ // ADC_DMA_CompleteFlag = 2; // 标记后半缓冲区就绪,后400个数据已就绪 // Current_ADC_Buffer = &amp;ADC_Dual_Value[200]; //指针指向缓冲区【400】 // DMA_ClearITPendingBit(DMA1_IT_TC1); // } } void TIM4_UP_IRQHandler(void) { if(TIM_GetITStatus(TIM4,TIM_IT_Update)) { Sam_Vol = (uint16_t)(filtered_ADC_volt(Volt_Value)*1000); //采样电压,到时去实验测阻值比来乘上系数得到输出电压 // Sam_Cur = (uint16_t)(filtered_ADC_volt(Cur_Value)*1000/Cur_Gain); //采样电流的 // vol_DAC = (uint16_t)(filtered_ADC_volt(Volt_Value)*1000*Void_Gain);//输出电压 // // OLED_ShowNum(56, 0,vol_DAC/10000,1,OLED_8X16); //十位 // OLED_ShowNum(64, 0,vol_DAC%10000/1000,1,OLED_8X16); //个位 // OLED_ShowChar(72, 0,&#39;.&#39;,OLED_8X16); // OLED_ShowNum(80, 0,vol_DAC%1000/100,1,OLED_8X16); //十分位 // OLED_ShowNum(88, 0,vol_DAC%100/10,1,OLED_8X16); //百分位 // OLED_ShowNum(96, 0,vol_DAC%10,1,OLED_8X16); //千分位 // OLED_ShowChar(112,0,&#39;V&#39;,OLED_8X16); OLED_ShowNum(72,16,Sam_Vol/10000,1,OLED_8X16); //十位 OLED_ShowNum(80,16,Sam_Vol%10000/1000,1,OLED_8X16); //个位 OLED_ShowChar(88,16,&#39;.&#39;,OLED_8X16); OLED_ShowNum(96,16,Sam_Vol%1000/100,1,OLED_8X16); //十分位 OLED_ShowNum(104,16,Sam_Vol%100/10,1,OLED_8X16); //百分位 OLED_ShowNum(112,16,Sam_Vol%10,1,OLED_8X16); //千分位 OLED_ShowChar(120,16,&#39;V&#39;,OLED_8X16); // OLED_ShowNum(72, 32,Sam_Cur/10000,1,OLED_8X16); //十位 // OLED_ShowNum(80, 32,Sam_Cur%10000/1000,1,OLED_8X16); //个位 // OLED_ShowChar(88, 32,&#39;.&#39;,OLED_8X16); // OLED_ShowNum(96, 32,Sam_Cur%1000/100,1,OLED_8X16); //十分位 // OLED_ShowNum(104, 32,Sam_Cur%100/10,1,OLED_8X16); //百分位 // OLED_ShowNum(112, 32,Sam_Cur%10,1,OLED_8X16); //千分位 // OLED_ShowChar(120,32,&#39;A&#39;,OLED_8X16); // OLED_ShowNum(0,48,PWM_GetCCR(TIM1,1),4,OLED_8X16); //OLED_Update(); // OLED_UpdateArea(0,16,128,16); TIM_ClearITPendingBit(TIM4,TIM_IT_Update); } } PID.c:#include &quot;stm32f10x.h&quot; // Device header #include &quot;PID.h&quot; #include &quot;SPWM.h&quot; #include &lt;math.h&gt; #include &quot;ADC_DMA.h&quot; #include &lt;string.h&gt; #define Volt_Target 2.0f //目标电压 #define Cur_Max 5.0f #define Steady_State_rate 0.0007f // 1%变化视为稳态 #define Enter_Steady_Count 10 // 连续20次在阈值内视为稳态 #define Max_Steady_Step 8 // 稳态时CCR最大步长(0.001占空比步长) #define SAMPLE_SIZE 64 // 采样数组大小 float Gain = 1.0f; //SPWM幅值缩放因子 uint8_t Control_Flag =0; PIDController pid = {.in_steady_state = 0, .steady_count = 0}; void Timer3_Init(void) //使用TIM3做定时中断 { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); TIM_InternalClockConfig(TIM3); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 4000-1; //2ms的定时中断 TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3,&amp;TIM_TimeBaseInitStructure); TIM_ClearFlag(TIM3,TIM_IT_Update); TIM_ITConfig(TIM3,TIM_EventSource_Update,ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&amp;NVIC_InitStructure); TIM_Cmd(TIM3,ENABLE); } void PID_Init(float Volt_Kp,float Volt_Ki, float Volt_Kd,float Cur_Kp,float Cur_Ki, float Cur_Kd) { // 初始PID参数(需调试优化) pid.Volt_Kp = Volt_Kp; // 电压比例系数 pid.Volt_Ki = Volt_Ki; // 电压积分系数 pid.Volt_Kd = Volt_Kd; // 电压微分系数 pid.Cur_Kp = Cur_Kp; // 电压比例系数 pid.Cur_Ki = Cur_Ki; // 电压积分系数 pid.Cur_Kd = Cur_Kd; // 电压微分系数 pid.Volt_integral_sum = 0; //电压积分累加项 pid.Cur_integral_sum = 0; //电流积分累加项 pid.Max_Current = 0; //最大电流有效值 pid.Cur_Vref = 0; pid.Volt_prev_error = 0; //电压上次误差 pid.Cur_prev_error = 0; //电流上次误差 // 输出限幅 pid.output_min = 0.1f; pid.output_max = 1.05f; Timer3_Init(); } float PID_Compute(float Volt_Rms ,float Cur_Rms) { // 计算当前误差 (电压误差) float Volt_error = Volt_Target - Volt_Rms; float error_threshold = Volt_Target * Steady_State_rate; //进入稳态误差的小小误差 if(fabs(Volt_error) &lt;= error_threshold) //判断误差值连续20&lt;0.01V的电压时进入稳态 { pid.steady_count++; } else { pid.steady_count = 0; pid.in_steady_state = 0; } if(pid.steady_count &gt;= Enter_Steady_Count) { pid.in_steady_state = 1; } // 计算P项 float Volt_P = pid.Volt_Kp * Volt_error; // 计算I项 if(pid.in_steady_state) // 稳态时仅当|error|较大时才积分 { if(fabs(Volt_error) &gt; Steady_State_rate* Volt_Target/1) { pid.Volt_integral_sum += Volt_error; } } else // 动态变化中正常积分 { pid.Volt_integral_sum += Volt_error; } float Volt_I = pid.Volt_Ki * pid.Volt_integral_sum; // 计算D项 (基于误差变化率) float error_derivative = (Volt_error - pid.Volt_prev_error); float Volt_D = pid.Volt_Kd * error_derivative; // 计算电压外环输出 pid.Cur_Vref = Volt_P + Volt_I + Volt_D; // 输出限幅处理 if(pid.Cur_Vref &gt; pid.Max_Current) { pid.Cur_Vref = pid.Max_Current; } else if(pid.Cur_Vref &lt; 0) { pid.Cur_Vref = 0; } pid.Volt_prev_error = Volt_error; float Cur_error = pid.Cur_Vref - Cur_Rms; //内环P float Cur_P = pid.Cur_Kp * Cur_error; //内环I pid.Cur_integral_sum += Cur_error; float Cur_I = pid.Cur_Ki * pid.Cur_integral_sum; //内环D float Cur_D = pid.Cur_Kd * (Cur_error - pid.Cur_prev_error); float output = Cur_P + Cur_I + Cur_D; pid.Cur_prev_error = Cur_error; //输出限幅 if(output &gt; pid.output_max) { output = pid.output_max; if(Cur_error &gt; 0)pid.Cur_integral_sum -= Cur_error; //超则回退积分 } if(output &lt; pid.output_min) { output = pid.output_min; if(Cur_error &lt; 0)pid.Cur_integral_sum -= Cur_error; } return output; } float filtered_ADC_volt(uint16_t *adc_values) //中值滤波函数,滤波采样数组中的数据 { uint16_t temp[SAMPLE_SIZE]; // 1. for(uint8_t i=0; i&lt;SAMPLE_SIZE; i++) { temp[i] = adc_values[i]; } // 2. 排序 for(uint8_t i=0; i&lt;SAMPLE_SIZE-1; i++) { for(uint8_t j=0; j&lt;SAMPLE_SIZE-1-i; j++) { if(temp[j] &gt; temp[j+1]) { uint16_t swap = temp[j]; temp[j] = temp[j+1]; temp[j+1] = swap; } } } // 3. 去掉最大最小值并计算均值 uint32_t sum = 0; for(uint8_t i=5; i&lt;SAMPLE_SIZE-5; i++) // 掐头去尾(去掉最大最小值) { sum += temp[i]; } float result = sum / (float)(SAMPLE_SIZE - 10); return result*3.3f/4095.0; //返回数组中去除最大最小值后的平均值(注:该值为模拟量) } float Rms_ADC_Volt(uint16_t *adc_values) { uint32_t Sum = 0; float volt; for(uint16_t i=0;i&lt;SAMPLE_SIZE;i+=4) { Sum += (uint32_t)(adc_values[i] * adc_values[i]); Sum += (uint32_t)(adc_values[i+1] * adc_values[i+1]); Sum += (uint32_t)(adc_values[i+2] * adc_values[i+2]); Sum += (uint32_t)(adc_values[i+3] * adc_values[i+3]); } volt = 3.3f*sqrt((float)Sum/SAMPLE_SIZE)/4095.0f; return volt; } void Control_Loop(void) { Rms_WindowsUpdate(); //更新平方和 float Volt_Rms = Get_Volt_RmsValue(); float Cur_Rms =Get_Cur_RmsValue(); Gain = PID_Compute(Volt_Rms,Cur_Rms); //求采样有效值(0~3.3V)送入PID,返回缩放增益Gain SPWM_Update(Gain,Current_SPWM_ReadyBuffer); } void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { Control_Flag = 1; TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } } 请检查代码并分析,谢谢
07-09
启动树莓派后,新建文件夹7_joystick_PS2,进入编程\Mu.,在文件夹下建立joystick_PS2.py文件和PCF8591.py文件(参见实验PCF8591模数/数模转换器实验模块文件),按照实验要求,完成相应的功能。 # 说明:PS2操作杆实验,该实验依赖于pcf8591模块 ##################################################### import PCF8591 as ADC import time # 初始化 def makerobo_setup(): ADC.setup(0x48)# 设置PCF8591模块地址 global makerobo_state # 状态变量 # 方向判断函数 def makerobo_direction(): state = [&#39;home&#39;, &#39;up&#39;, &#39;down&#39;, &#39;left&#39;, &#39;right&#39;, &#39;pressed&#39;] # 方向状态信息 i = 0 if ADC.read(0) &lt;= 30: i = 1# up方向 if ADC.read(0) &gt;= 225: i = 2# down方向 if ADC.read(1) &gt;= 225: i = 4# left方向 if ADC.read(1) &lt;= 30: i = 3# right方向 if ADC.read(2) == 0 and ADC.read(1) == 128: i = 5# Button按下 # home位置 if ADC.read(0) - 125 &lt; 15 and ADC.read(0) - 125 &gt; -15and ADC.read(1) - 125 &lt; 15 and ADC.read(1) - 125 &gt; -15 and ADC.read(2) == 255: i = 0 return state[i] # 返回状态 # 循环函数 def makerobo_loop(): makerobo_status = &#39;&#39; # 状态值赋空值 while True: makerobo_tmp = makerobo_direction() # 调用方向判断函数 if makerobo_tmp != None and makerobo_tmp != makerobo_status: # 判断状态是否发生改变 print (makerobo_tmp) # 打印出方向位 makerobo_status = makerobo_tmp # 把当前状态赋给状态值,以防止同一状态多次打印 # 异常处理函数 def destroy(): pass # 程序入口 if __name__ == &#39;__main__&#39;: makerobo_setup() # 初始化 try: makerobo_loop() # 调用循环函数 except KeyboardInterrupt: # 当按下Ctrl+C时,将执行destroy()子程序。 destroy() # 调用释放函数 下一节上一节1、显示操纵杆X、Y和Z轴的数值。 2、增加LED灯模块,根据操纵杆的位置控制LED灯的明暗变化。 下一节上一节
04-03
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值