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

📄 mbc_pwmoutput.m

📁 simulink real-time workshop for dragon12 development board from
💻 M
字号:
function [pulsepinstr, signportstr, signpinstr, periodstr, clkABstr, resolutionstr] = mbc_pwmoutput(sampletime, resolution, PWMper, pulse_pin, sign_port, sign_pin, Vmax, sig_mon)

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

% Check the PWM period value
if ((PWMper < 0) | (PWMper > 179))
   	disp('PWM: Inadmissible value for PWM period.')
end

% return period string for display...
periodstr = num2str(PWMper);

% feasible period -> check if possible in conjunction with the chosen resolution
if ((resolution == 1) && (PWMper > 0.699))
	disp('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
	
% 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(PWMper > basePERIOD*256*cascadeFactor*(2^PCK)*useSCL*PWMSCL)
    if(PWMSCL < 256)
        PWMSCL = PWMSCL + 1;
	else
        % exhausted capabilities of PWMSCL -> also use prescaler
        PCK = PCK + 1;          % additional factor 2
        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([PWMper/(basePERIOD*256*cascadeFactor*(2^PCK)*useSCL*PWMSCL)] * 256*cascadeFactor);
myPERIODstr = num2str(myPERIOD);
	
% 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')
sign_pin = sign_pin - 1;
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);

% Check port number
port_strings = {'PORTA', 'PORTB', 'PTH', 'PTJ', 'PTM', 'PTP', 'PTS', 'PTT'};
ddr_strings = {'DDRA', 'DDRB', 'DDRH', 'DDRJ', 'DDRM', 'DDRP', 'DDRS', 'DDRT'};
signportstr = port_strings{sign_port};
signportddrstr = ddr_strings{sign_port};


% Check if sign_pin number is available on the chosen port
valid_pin = { [0 1 2 3 4 5 6 7]; ...
		      [0 1 2 3 4 5 6 7]; ...
		      [0 1 2 3 4 5 6 7]; ...
		      [0 1 6 7]; ...
		      [0 1 2 3 4 5 6 7]; ...
		      [0 1 2 3 4 5 6 7]; ...
		      [0 1 2 3 4 5 6 7]; ...
		      [0 1 2 3 4 5 6 7] };

% Check the sign pin number and set signpinstr (display)
if(any(setdiff(sign_pin, valid_pin{sign_port})))
	signpinstr = '???';
	fprintf ('PWM: Inadmissible sign pin number for %s.\n', signportstr);
else
	signpinstr = num2str(sign_pin);
end

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

% Create resource keywords to be reserved in resource database
modelRTWFields = struct( 'pulsepinStr', pulsepinstr, ...
	                     'pulsepinMask', pulsepinmask, ...
						 'signportStr', signportstr, ...
						 'signportddrStr', signportddrstr, ...
						 'signpinMask', signpinmask, ...
						 'signpinStr', signpinstr, ...
						 'resolutionStr', resolutionstr, ...
						 'CLKselectStr', CLKselectstr, ...
						 'useSCLStr', useSCLstr, ...
						 'PCKStr', PCKstr, ...
						 'PWMSCLStr', PWMSCLstr, ...
					     'PERIODStr', myPERIODstr );

%debug
%modelRTWFields

% Insert modelRTWFields in the I/O block S-Function containing the Tag 'MC9S12DriverDataBlock'
% to set the block 'Tag' use: 
% >> kk = get_param(find_system(gcb, 'FollowLinks', 'on', 'LookUnderMasks', 'all', 'Name', 'MC'), 'Tag')
% >> 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 ('PWM: Maximum voltage has to be positive !\n');
end


% optional: signal monitoring

% replace parameter 'sig_mon' by '0' or '1'
% sPars = get_param ([gcb, '/MC'], 'Parameters');
% sPars = strrep(sPars, 'sig_mon', num2str(sig_mon));
% set_param([gcb, '/MC'], 'Parameters', sPars);

if(sig_mon == 1)
    
    % check if output needs to be generated
   op = get_param (gcb, 'OutputPorts');

   if(length(op) == 0)

      % yes -> modify mask

      % inactivate link to library block
      if(~strcmp(get_param(gcb, 'LinkStatus'),'inactive'))
         % disable library link
         set_param(gcb, 'LinkStatus', 'inactive');
      end

      % add block output
      add_block ('built-in/Outport', [gcb, '/Out1']);
      set_param ([gcb, '/Out1'], 'Position', get_param ([gcb, '/In1'], 'Position') + [250 0 250 0])

      % add output port to the 'MC' block
      sPars = get_param ([gcb, '/MC'], 'Parameters');
      sPars = strrep(sPars, 'sig_mon', '1');              % change parameter 'sig_mon' to '1'
      set_param([gcb, '/MC'], 'Parameters', sPars);       % force port to appear...
      sPars = strrep(sPars, '1', 'sig_mon');              % restore original parameter 'sig_mon'
      set_param([gcb, '/MC'], 'Parameters', sPars);

      % connect new MC output port to the new output block
      add_line (gcb, 'MC/1', 'Out1/1', 'autorouting', 'on');

   end

else

   % no signal monitoring -> check if output needs to be deleted
   op = get_param (gcb, 'OutputPorts');

   if(length(op) > 0)

      if(~strcmp(get_param(gcb, 'LinkStatus'),'inactive'))
         % disable library link
         set_param(gcb, 'LinkStatus', 'inactive');
      end

      % delete line between the MC port and the output block
      delete_line (gcb, 'MC/1', 'Out1/1');

      % delete output port
      delete_block([gcb, '/Out1']);

      % remove output port of the MC block
      sPars = get_param ([gcb, '/MC'], 'Parameters');
      sPars = strrep(sPars, 'sig_mon', '0');              % change parameter 'sig_mon' to '0'
      set_param([gcb, '/MC'], 'Parameters', sPars);       % force port to disappear
      sPars = strrep(sPars, '0', 'sig_mon');              % restore original parameter 'sig_mon'
      set_param([gcb, '/MC'], 'Parameters', sPars);

   end

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 + -