⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbc_servopwmoutput.m

📁 simulink real-time workshop for dragon12 development board from
💻 M
字号:
function [pulsepinstr, periodstr, clkABstr, resolutionstr] = mbc_servopwmoutput(sampletime, PWMperiod, minwidth, maxwidth, resolution, pulse_pin, Vmax)

% Check the sample time:
if((sampletime < 0) & (sampletime ~= -1))
   fprintf ('Servo motor PWM: Inadmissible sample time !\n');
end

% feasible period -> check if possible in conjunction with the chosen resolution
if ((resolution == 1) && (PWMperiod > 0.699))
	disp('Servo motor PWM: Inadmissible value for PWM period in 8-bit mode, switching to 16-bit resolution.')
	resolution = 2;
	kk = find_system(gcb, 'FollowLinks', 'on');
	ll = get_param(kk{:}, 'DialogParameters');
	modified_resolution_text = ll.resolution.Enum;
	set_param(kk{:}, 'resolution', modified_resolution_text{resolution});
end

% valid period -> calculate PWM clock parameters	
% base period : 1/[24 MHz] = 42 ns
basePERIOD = 1/24e6;

% check if we need to cascade timers... (1 -> 8-bit, 2 -> 16-bit)
if(resolution == 2) 
	cascadeFactor = 256;
	resolutionstr = '16';
else
	cascadeFactor = 1;		
	resolutionstr = '8';
end
	
% period... for display
periodstr = num2str(PWMperiod);

% determine period settings
useSCL = 2;       % implicit factor '2' of the S(caled) clock
PCK = 0;          % PCK[0-2] can range from 0 to 7  ==>  prescale values /1 ... /128
PWMSCL = 1;       % PWMSCL[0-7] can range from 1 to 256
while(PWMperiod > basePERIOD*256*cascadeFactor*(2^PCK)*useSCL*PWMSCL)
    if(PWMSCL < 256)
        PWMSCL = PWMSCL + 1;
	else
        % exhausted capabilities of PWMSCL -> also use prescaler
        PCK = PCK + 1;
        PWMSCL = 128;           % restart period search at 1/2 the PWMSCL value
	end
end
	
% determine period value
% first part [] is the fraction, second part is the full scale value
myPERIOD = round([PWMperiod/(basePERIOD*256*cascadeFactor*(2^PCK)*useSCL*PWMSCL)] * 256*cascadeFactor);
myPERIODstr = num2str(myPERIOD);
	
% determine minimum and maximum duty cycle
mydutyMIN = round([minwidth/(basePERIOD*256*cascadeFactor*(2^PCK)*useSCL*PWMSCL)] * 256*cascadeFactor);
mydutyMINstr = num2str(mydutyMIN);
mydutyMAX = round([maxwidth/(basePERIOD*256*cascadeFactor*(2^PCK)*useSCL*PWMSCL)] * 256*cascadeFactor);
mydutyMAXstr = num2str(mydutyMAX);

% factor 256 is represented by PWMSCL = 0
if(PWMSCL == 256)
    PWMSCL = 0;
end
		

% set timing variables to be passed to the TLC
PCKstr = num2str(PCK);
PWMSCLstr = num2str(PWMSCL);


% adjust pin numbers (evaluate to '1 ... 8' rather than '0 ... 7')
pulse_pin = pulse_pin - 1;

% define pulse pin/port strings
pulsepinstr = num2str(pulse_pin);
pulseportstr = 'PTP';			% fixed, display only

% make sure the 'pulse_pin' is valid in 16-bit mode...
output_channels_16bit = {'1', '3', '5', '7'};
kk = find_system(gcb, 'FollowLinks', 'on');
ll = get_param(kk{:}, 'DialogParameters');
modified_channel_text = ll.pulse_pin.Enum;
if((resolution == 2) & ~ismember(pulsepinstr, output_channels_16bit))
	disp(['PWM: 16-bit mode only possible on channels 1, 3, 5 or 7  --  adjusting channel from ' num2str(pulse_pin) ' to ' num2str(pulse_pin+1)])
	pulse_pin = pulse_pin + 1;
	pulsepinstr = num2str(pulse_pin);
	set_param(kk{:}, 'pulse_pin', modified_channel_text{pulse_pin+1});
end


% useSCL : indicates if scaled clock is to be used (1) or not (0)
useSCLstr = num2str(useSCL-1);

% determine clock source
PWM_channels_A = { '0', '1', '4', '5' };
if(ismember(pulsepinstr, PWM_channels_A))
	CLKselect = 0;          % A (SA)
    clkABstr = 'A';         % % return clock source string
else
	CLKselect = 1;          % B (SB)
    clkABstr = 'B';         % % return clock source string
end

CLKselectstr = num2str(CLKselect);


% assemble masks ('pulse' as well as 'sign')
pulsepinmask = num2str(2^pulse_pin);

% Create resource keywords to be reserved in resource database
modelRTWFields = struct( 'pulsepinStr', pulsepinstr, ...
	                     'pulsepinMask', pulsepinmask, ...
						 'resolutionStr', resolutionstr, ...
						 'CLKselectStr', CLKselectstr, ...
						 'useSCLStr', useSCLstr, ...
						 'PCKStr', PCKstr, ...
						 'PWMSCLStr', PWMSCLstr, ...
						 'dutyMINStr', mydutyMINstr, ...
						 'dutyMAXStr', mydutyMAXstr, ...
					     'PERIODStr', myPERIODstr );

%debug
%modelRTWFields

% Insert modelRTWFields in the I/O block S-Function containing the Tag 'MC9S12DriverDataBlock'
% to set the block 'Tag' use: 
% >> kk = find_system(gcb, 'FollowLinks', 'on', 'LookUnderMasks', 'all', 'Name', 'servo pwm')
% >> set_param(kk{:}, 'Tag', 'MC9S12target_pwm')
% ... then save the block / model (fw-02-05)
MC9S12DriverDataBlock = find_system(gcb, 'FollowLinks', 'on', 'LookUnderMasks', 'all', 'Tag', 'MC9S12target_pwm');
set_param(MC9S12DriverDataBlock{1}, 'RTWdata', modelRTWFields);


% Check the maximum voltage:
if (Vmax < 0)
   fprintf ('Servo motor PWM: Saturation level has to be positive !\n');
end



% =========================================================================
% synchronize blocks -> resolution has to be the same for all
% only the last block in the model performs this section
% =========================================================================

MC9S12PWMBlocks = find_system(gcs, 'FollowLinks', 'on', 'LookUnderMasks', 'all', 'Tag', 'MC9S12target_pwm');

amlast = 0;
myResolution = [];
myCLKselection = [];
mySCLused = [];
myPCK = [];
myPWMSCL = [];
myPERIOD = [];
for(i = 1:length(MC9S12PWMBlocks))
    
    % get current settings
    kk = get_param(MC9S12PWMBlocks{i}, 'RTWData');
    myResolution = [myResolution str2num(kk.resolutionStr)];
    myCLKselection = [myCLKselection str2num(kk.CLKselectStr)];
    mySCLused = [mySCLused str2num(kk.useSCLStr)];
    myPCK = [myPCK str2num(kk.PCKStr)];
    
    PWMSCLtemp = str2num(kk.PWMSCLStr);
    if(PWMSCLtemp == 0)
        myPWMSCL = [myPWMSCL 256];               % '0' stands for '256'
    else
        myPWMSCL = [myPWMSCL PWMSCLtemp];        % all other values...
    end
    
    myPERIOD = [myPERIOD str2num(kk.PERIODStr)];
    
    % determine if we're the last timer block to get updated
    if(strcmp(MC9S12PWMBlocks{i}, MC9S12DriverDataBlock{1}) & (i == length(MC9S12PWMBlocks)))
        amlast = 1;
    end
end

if(amlast == 1)
    
    % separate A-clk blocks and B-clk blocks
    Aclks = find(myCLKselection == 0);
    Bclks = find(myCLKselection == 1);

    % synchronize A-blocks
    myResA = myResolution(Aclks);
    myCLKselA = myCLKselection(Aclks);
    mySCLusedA = mySCLused(Aclks);
    myPCKA = myPCK(Aclks);
    myPWMSCLA = myPWMSCL(Aclks);
    myPERIODA = myPERIOD(Aclks);

    % determine slowest A-clk
    myPCKAslowest = max(myPCKA);
    myPCKAslowest_IDX = find(myPCKA == myPCKAslowest);
    myPWMSCLAslowest = max(myPWMSCLA(myPCKAslowest_IDX));
    myPWMSCLAslowest_IDX = max(find(myPWMSCLA(myPCKAslowest_IDX) == myPWMSCLAslowest));     % max -> can just choose any (doesnt' matter)
    
    % adjust clock settings of all A-clk blocks to match those of the slowest one
    for(i = 1:length(Aclks))
        
        kk = get_param(MC9S12PWMBlocks{Aclks(i)}, 'RTWData');
        
        % recalculate new period
        ll = get_param(get_param(MC9S12PWMBlocks{Aclks(i)}, 'Parent'), 'MaskValues');
        blockPeriod = str2num(ll{3});

        newPERIOD = round([blockPeriod/(basePERIOD*256*cascadeFactor*(2^myPCKAslowest)*useSCL*myPWMSCLAslowest)] * 256*cascadeFactor);
        kk.PERIODStr = num2str(newPERIOD);
        
        if(myPWMSCLAslowest == 256)
            kk.PWMSCLStr = '0';                             % 256 is encoded as '0'
        else    
            kk.PWMSCLStr = num2str(myPWMSCLAslowest);       % all other values are as they are
        end
        
        kk.PCKStr = num2str(myPCKAslowest);
        
        % set adjusted parameters
        set_param(MC9S12PWMBlocks{Aclks(i)}, 'RTWData', kk);
        
    end
    
        
    % synchronize B-blocks
    myResB = myResolution(Bclks);
    myCLKselB = myCLKselection(Bclks);
    mySCLusedB = mySCLused(Bclks);
    myPCKB = myPCK(Bclks);
    myPWMSCLB = myPWMSCL(Bclks);
    myPERIODB = myPERIOD(Bclks);

    % determine slowest B-clk
    myPCKBslowest = max(myPCKB);
    myPCKBslowest_IDX = find(myPCKB == myPCKBslowest);
    myPWMSCLBslowest = max(myPWMSCLB(myPCKBslowest_IDX));
    myPWMSCLBslowest_IDX = max(find(myPWMSCLB(myPCKBslowest_IDX) == myPWMSCLBslowest));     % max -> can just choose any (doesnt' matter)
    
    % adjust clock settings of all B-clk blocks to match those of the slowest one
    for(i = 1:length(Bclks))
        
        kk = get_param(MC9S12PWMBlocks{Bclks(i)}, 'RTWData');
        
        % recalculate new period
        ll = get_param(get_param(MC9S12PWMBlocks{Bclks(i)}, 'Parent'), 'MaskValues');
        blockPeriod = str2num(ll{3});

        newPERIOD = round([blockPeriod/(basePERIOD*256*cascadeFactor*(2^myPCKBslowest)*useSCL*myPWMSCLBslowest)] * 256*cascadeFactor);
        kk.PERIODStr = num2str(newPERIOD);
        
        if(myPWMSCLBslowest == 256)
            kk.PWMSCLStr = '0';                             % 256 is encoded as '0'
        else    
            kk.PWMSCLStr = num2str(myPWMSCLBslowest);       % all other values are as they are
        end
        
        kk.PCKStr = num2str(myPCKBslowest);
        
        % set adjusted parameters
        set_param(MC9S12PWMBlocks{Bclks(i)}, 'RTWData', kk);
        
    end
    
    save_system;

end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -