S12PWM8B8CV2
Features:
Block Diagram:
Register Descriptions:
PWME:
PWM通道波形输出使能寄存器:
- PWMEx=0 关联的PWM输出关闭;
- PWMEx=1 关联的PWM输出使能;
- CON01 = 1:PWME0位无效,PWM0关闭,PWM1 16bit模式;
- CON23 = 1:PWME2位无效,PWM2关闭,PWM3 16bit模式;
- CON45 = 1:PWME4位无效,PWM4关闭,PWM5 16bit模式;
- CON67 = 1:PWME6位无效,PWM6关闭,PWM7 16bit模式;
- CONxx = 0:PWM0~PWM7 全部可使能且只能是8bit模式;
注意:PWM(0,2,4,6)的使能控制与CONxx设置右关,PWM(1,3,5,7)可以设置为16bit PWM。CONxx@PWMCTL;
PWMPOL:
PWM极性控制:
- PPOLx = 0 :beginning低电平,duty高电平;
- PPOLx = 1 :beginning高电平,duty低电平;
PWMCLK:
PWM时钟选择寄存器:
- PCLKx = 0: PWM 时钟源使用时钟A 或 时钟B;
- PCLKx = 1: PWM 时钟源使用时钟SA 或 时钟SB;
注意:PWM时钟选择需要与PWMCLKAB配合设置;
PWMPRCLK:
时钟A和时钟B分频系数寄存器:
- PWMPRCLK[6:4] clock B分频系数;
- PWMPRCLK[2:0] clock A分频系数;
- 0x0 : 总线时钟
- 0x1 : 总线时钟/2
- 0x2 : 总线时钟/4
- 0x3 : 总线时钟/8
- 0x4 : 总线时钟/16
- 0x5 : 总线时钟/32
- 0x6 : 总线时钟/64
- 0x7 : 总线时钟/128
PWMCAE:
PWM中间对齐使能寄存器:
扫描二维码关注公众号,回复:
12407433 查看本文章
- CAEx=0,关联PWM通道左对齐输出模式;
- CAEx=1,关联PWM通道中间对齐输出模式;
PWMCTL:
PWM控制寄存器:
- CON01 = 1:PWME0位无效,PWM0关闭,PWM1 16bit模式;
- CON23 = 1:PWME2位无效,PWM2关闭,PWM3 16bit模式;
- CON45 = 1:PWME4位无效,PWM4关闭,PWM5 16bit模式;
- CON67 = 1:PWME6位无效,PWM6关闭,PWM7 16bit模式;
- CONxx = 0:PWM0~PWM7 全部可使能且只能是8bit模式;
PWMCLKAB:
PWM时钟A/B选择寄存器:
- PCLKABx = 0: PWMx时钟源使用时钟B或时钟SB;
- PCLKABx = 1: PWMx时钟源使用时钟A或时钟SA;
注意:PWMx的时钟源设置与PWMCLK设置有关;
PWMSCLA:
CLock SA时钟频率设置:
- Clock SA = Clock A/(2*PWMSCLA)
- 如果PWMSCLA=0x00 实际值被看出最大scale值256,即Clock SB = Clock B/512;
PWMSCLB:
CLock SB时钟频率设置:
- Clock SB = Clock B/(2*PWMSCLB)
- 如果PWMSCLB=0x00 实际值被看出最大scale值256,即Clock SB = Clock B/512;
PWMCNTx:
PWMPERx:
PWMDTYx:
Function Description:
PWMx使用步骤总结:
1.PWMx工作模式设置:8bit或16bit模式;
- 8bit模式PWM0-PWM7可输出波形;
- 16bit模式PWM[1,3,5,7]可以输出波形,PWM[0,2,4,6]不可用;
- PWMCTL_CON01=1 : PWM[0,1]联结为16位PWM,PWM1使能;
- PWMCTL_CON23=1 : PWM[2,3]联结为16位PWM,PWM3使能;
- PWMCTL_CON45=1 : PWM[4,5]联结为16位PWM,PWM5使能;
- PWMCTL_CON67=1 : PWM[6,7]联结为16位PWM,PWM7使能;
2.PWMx极性设置:
- PWMPOL[7:0] PWMx极性;
- PWMPOL_PPOLx=0: PWMx低电平有效;
- PWMPOL_PPOLx=1: PWMx高电平有效;
3.PWMx对齐方式设置:
- PWMCAE[7:0] PWMx对齐方式;
- PWMCAE_CAEx=0:PWMx左对齐;
- PWMCAE_CAEx=1:PWMx中心对齐;
4.时钟A、时钟B分频系数设置:
- PWMPRCLK[6:4] CLOCK B分频系数,PWMPRCLK[2:0] CLOCK A分频系数。
- 时钟A/B频率=fBUS/分频系数A/B。
PWMPRCLK[6:4](时钟B) | PWMPRCLK[2:0](时钟A) | 时钟频率 |
---|---|---|
0x0 | 0x0 | Bus clock |
0x1 | 0x1 | Bus clock/2 |
0x2 | 0x2 | Bus clock/4 |
0x3 | 0x3 | Bus clock/8 |
0x4 | 0x4 | Bus clock/16 |
0x5 | 0x5 | Bus clock32 |
0x6 | 0x6 | Bus clock/64 |
0x7 | 0x7 | Bus clock/128 |
5.PWMx时钟源配置:
- PWMCLKAB[x] = 0, PWMx CLock A;
- PWMCLKAB[x] = 1, PWMx CLock B;
- PWMCLK[x] = 0, PWMx Clock X, X|{A or B};
- PWMCLK[x] = 1, PWMx Clock SX, SX|{SA or SB};
PWM[0,1,4,5] 时钟源选择:
PCLKAB[0,1,4,5] | PWMCLK[0,1,4,5] | 时钟源选择 |
---|---|---|
0 | 0 | Clock A |
0 | 1 | Clock SA |
1 | 0 | Clock B |
1 | 1 | Clock SB |
PWM[2,3,6,7] 时钟源选择:
PCLKAB[2,3,6,7] | PWMCLK[2,3,6,7] | 时钟源选择 |
---|---|---|
0 | 0 | Clock A |
0 | 1 | Clock SA |
1 | 0 | Clock B |
1 | 1 | Clock SB |
6.时钟SA,SB频率设置:
PWMSCLA、PWMSCLB直接赋值十进制数值,(如果为0实际被看作最大比例值256)SA,SB的频率计算公式如下:
- CLock SA时钟频率设置,Clock SA = Clock A/(2*PWMSCLA);
- CLock SB时钟频率设置,Clock SB = Clock B/(2*PWMSCLB);
7.PWMx周期设置:
- PWMx Frequency = Clock(A,SA,B,SB)/PWMPERx;
- 寄存器 16位模式PWMPER01/23/45/67, 8位模式:PWMPER0/1/2/3/4/5/6/7;
8.PWMx占空比设置:
- Polarity=0(PPOLx=0) Duty Cycle = [(PWMPERx-PWMDTYx)/PWMPERx]*100%;
- Polarity=1(PPOLx=1) Duty Cycle = [PWMDTYx/PWMPERx]*100%
- 寄存器 16位模式PWMDTY01/23/45/67,8位模式PWMDTY0/1/2/3/4/5/6/7
9.PWMx使能输出波形:
- PWMEx=1,使能PWM输出;
- 寄存器 PWME_PWME1/2/3/4/5/6/7;
示例代码:
PWM[1,3,5,7] 16位模式:
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define D_BUSCLK_FREQ (16000000) // 总线频率 16MHz
#define D_SCI_BAUDRATE (9600) // 串口波特率
/*************************************************************/
/* 串口发送函数 */
/*************************************************************/
void csi_send(unsigned char data)
{
while(!SCI0SR1_TDRE); //等待发送数据寄存器(缓冲器)为空
SCI0DRL = data;
}
/*************************************************************/
/* 串口接收函数 */
/*************************************************************/
unsigned char csi_receive(void)
{
while(!SCI0SR1_RDRF); //等待发送数据寄存器满
return(SCI0DRL);
}
/*************************************************************/
/** 定义了这个两个接口就可以使用printf函数格式化输出 **/
/** TERMIO_PutChar **/
/** TERMIO_GetChar **/
/*************************************************************/
void TERMIO_PutChar(char ch){
csi_send((unsigned char)ch);
}
char TERMIO_GetChar(void){
return (char)csi_receive();
}
/*************************************************************/
/* 串口初始化函数 */
/*************************************************************/
void sci_init(void) {
SCI0BD = D_BUSCLK_FREQ/16/D_SCI_BAUDRATE; // 设置SCI0波特率 busCLK/16/BAUDRATE;
SCI0CR1 = 0x00; //设置SCI0为正常模式,八位数据位,无奇偶校验 7:LOOPS 6:SCISWAI 5:RSRC 4:M 3:WAKE 2:ILT 1:PE 0:PT
SCI0CR2 = 0x0C; //允许收发数据,允许收发中断功能 7:TIE, 6:TCIE, 5:RIE, 4:ILIE, 3:TE, 2:RE, 1:RWU, 0:SBK
}
/**
* @brief 锁相环 初始化
* @param none
* @return none
*/
void pll_init(void) {
CPMUPROT = 0x26; //保护时钟配置寄存器
CPMUCLKS_PSTP = 0; //禁用PLL
CPMUCLKS_PLLSEL = 1; //选择PLL作为系统时钟源
CPMUOSC_OSCE = 1; //外部晶振使能
while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能
// BUSCLK = (PLLCLK / 2) 总线频率=(锁相环频率/2)
#if 1
//fVOC= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1)
CPMUSYNR = 0x07;
//CPMUREFDIV = 0x0F; // PLLCLK:16M BUSCLK:8M
CPMUREFDIV = 0x07; // PLLCLK:32M BUSCLK:16M
//CPMUREFDIV = 0x03; // PLLCLK:64M BUSCLK:32M
#endif
#if 0
//fVOC配置 fVOC = 2*fREF*(SYNDIV +1)
//CPMUSYNR = 0x45; // PLLCLK:48M BUSCLK:24M
//CPMUSYNR = 0x44; // PLLCLK:40M BUSCLK:20M
//CPMUSYNR = 0x43; // PLLCLK:32M BUSCLK:16M
//CPMUSYNR = 0x42; // PLLCLK:24M BUSCLK:12M
CPMUSYNR = 0x01; // PLLCLK:16M BUSCLK:8M
CPMUREFDIV = 0x81;//REFDIV基准分频器配置
#endif
CPMUPOSTDIV = 0x00; // PLL CLOCK = VCO CLOCK / (POSTDIV + 1)
_asm(nop);
_asm(nop);
CPMUPLL=0x10; //锁相环调频启用,用以减少噪音
while(CPMUFLG_LOCK == 0); //等待PLL稳定
CPMUPROT = 0x00; //关闭保护时钟
CPMUCLKS_PLLSEL = 1; //使能PLL
}
void pwm_init(void)
{
// PWM1,3,5,7为16为PWM,PWM2,4,6,8使能无效;
PWMCTL_CON01 = 1;
PWMCTL_CON23 = 1;
PWMCTL_CON45 = 1;
PWMCTL_CON67 = 1;
// PWM1,3,5,7 极性设置0:低电平有效,1:高电平有效
PWMPOL_PPOL1 = 1;
PWMPOL_PPOL3 = 1;
PWMPOL_PPOL5 = 1;
PWMPOL_PPOL7 = 1;
// PWM1,3,5,7 对齐方式设置 0:左对齐,1:中心对齐
// PWMCAE = 0xFF; // 设置PWM0~PWM7中心对齐
PWMCAE_CAE1 = 0; //设置PWM1对齐方式 0:左对齐,1:中心对齐
PWMCAE_CAE3 = 1; //设置PWM3对齐方式 0:左对齐,1:中心对齐
PWMCAE_CAE5 = 1; //设置PWM5对齐方式 0:左对齐,1:中心对齐
PWMCAE_CAE7 = 1; //设置PWM7对齐方式 0:左对齐,1:中心对齐
/**
PWMPRCLK[6:4] CLOCK B分频系数,PWMPRCLK[2:0] CLOCK A分频系数
时钟A和时钟B分频系数设置 时钟A/B=fBUS/分频系数A/B:
---------------------------------------------------------------
| PWMPRCLK[6:4](时钟B) | PWMPRCLK[2:0](时钟A) | 时钟频率 |
|---------------------------------------------------------------|
| 0x0 | 0x0 | Bus clock |
|---------------------------------------------------------------|
| 0x1 | 0x1 | Bus clock/2 |
|---------------------------------------------------------------|
| 0x2 | 0x2 | Bus clock/4 |
|---------------------------------------------------------------|
| 0x3 | 0x3 | Bus clock/8 |
|---------------------------------------------------------------|
| 0x4 | 0x4 | Bus clock/16 |
|---------------------------------------------------------------|
| 0x5 | 0x5 | Bus clock/32 |
|---------------------------------------------------------------|
| 0x6 | 0x6 | Bus clock/64 |
|---------------------------------------------------------------|
| 0x7 | 0x7 | Bus clock/128 |
---------------------------------------------------------------
**/
PWMPRCLK = 0x44; // 时钟A和时钟B分频系数设置, 当值为0x4 1MHz = 16MHz/16分频系数;
/**
PWMCLKAB[x] = 0, PWMx CLock A;
PWMCLKAB[x] = 1, PWMx CLock B;
PWMCLK[x] = 0, PWMx Clock X, X|{A or B};
PWMCLK[x] = 1, PWMx Clock SX, SX|{SA or SB};
PWM[0,1,4,5] 时钟源选择:
---------------------------------------------------------------
| PCLKAB[0,1,4,5] | PWMCLK[0,1,4,5] | 时钟源选择 |
|---------------------------------------------------------------|
| 0 | 0 | Clock A |
|---------------------------------------------------------------|
| 0 | 1 | Clock SA |
|---------------------------------------------------------------|
| 1 | 0 | Clock B |
|---------------------------------------------------------------|
| 1 | 1 | Clock SB |
---------------------------------------------------------------
PWM[2,3,6,7] 时钟源选择:
---------------------------------------------------------------
| PCLKAB[2,3,6,7] | PWMCLK[2,3,6,7] | 时钟源选择 |
|---------------------------------------------------------------|
| 0 | 0 | Clock A |
|---------------------------------------------------------------|
| 0 | 1 | Clock SA |
|---------------------------------------------------------------|
| 1 | 0 | Clock B |
|---------------------------------------------------------------|
| 1 | 1 | Clock SB |
---------------------------------------------------------------
**/
// PWMCLKAB
// PWMCLK
// PWM1,3,5,7 时钟源设置
PWMCLKAB_PCLKAB1 = 0; //PWM1 Clock A
PWMCLK_PCLK1 = 0;
PWMCLKAB_PCLKAB3 = 1; //PWM3 Clock SA
PWMCLK_PCLK3 = 0;
PWMCLKAB_PCLKAB5 = 0; //PWM1 Clock B
PWMCLK_PCLK5 = 1;
PWMCLKAB_PCLKAB7 = 1; //PWM1 Clock SB
PWMCLK_PCLK7 = 1;
// PWM SA,SB时钟频率设置
PWMSCLA = 1; // CLock SA时钟频率设置,Clock SA = Clock A/(2*PWMSCLA) 如果PWMSCLA=0x00 实际值被看作最大比例值256,即Clock SA = Clock A/512;
PWMSCLB = 2; // CLock SB时钟频率设置,Clock SB = Clock B/(2*PWMSCLB) 如果PWMSCLB=0x00 实际值被看作最大比例值256,即Clock SB = Clock B/512;
// PWMx 周期设置
// PWMx Frequency = Clock(A,SA,B,SB)/PWMPERx
// PWM1,3,5,7 周期设置
PWMPER01 = 10000;
PWMPER23 = 2500;
PWMPER45 = 2500;
PWMPER67 = 2500;
// PWMx 占空比设置
// PWMx Duty Cycle(high time as a% of period):
// Polarity=0(PPOLx=0) Duty Cycle = [(PWMPERx-PWMDTYx)/PWMPERx]*100%
// Polarity=1(PPOLx=1) Duty Cycle = [PWMDTYx/PWMPERx]*100%
// PWM1,3,5,7 占空比设置
PWMDTY01 = 1000;
PWMDTY23 = 400;
PWMDTY45 = 600;
PWMDTY67 = 800;
// TODO:使能PWM1,3,5,7 波形输出
PWME_PWME1 = 1;
PWME_PWME3 = 1;
PWME_PWME5 = 1;
PWME_PWME7 = 1;
#if 0
PWMCTL_CON01= 1; //联结通道0,1为16位的PWM
PWMPOL_PPOL1= 1; //通道01的极性为高电平有效
PWMPRCLK = 0x44; //A时钟和B时钟的分频系数为16,频率为1MHz
PWMSCLA = 100; //SA时钟频率为5KHz
PWMSCLB = 100; //SB时钟频率为5KHz
PWMCLK =0x02; //通道01用SA时钟作为时钟源
PWMCAE = 0x02; //脉冲模式中央对齐模式
PWMPER01 = 2500; //通道01的周期为1Hz
PWMDTY01 = 500; //通道01的占空比为20%
PWME_PWME1 = 1; //使能通道01
#endif
}
void main(void) {
/* put your own code here */
DisableInterrupts;
pll_init();
sci_init();
pwm_init();
EnableInterrupts;
(void)printf("************* PWM **************\n");
for(;;) {
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
PWM[1,3,5,7]波形图:
PWM[0~7] 8位模式:
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define D_BUSCLK_FREQ (16000000) // 总线频率 16MHz
#define D_SCI_BAUDRATE (9600) // 串口波特率
/*************************************************************/
/* 串口发送函数 */
/*************************************************************/
void csi_send(unsigned char data)
{
while(!SCI0SR1_TDRE); //等待发送数据寄存器(缓冲器)为空
SCI0DRL = data;
}
/*************************************************************/
/* 串口接收函数 */
/*************************************************************/
unsigned char csi_receive(void)
{
while(!SCI0SR1_RDRF); //等待发送数据寄存器满
return(SCI0DRL);
}
/*************************************************************/
/** 定义了这个两个接口就可以使用printf函数格式化输出 **/
/** TERMIO_PutChar **/
/** TERMIO_GetChar **/
/*************************************************************/
void TERMIO_PutChar(char ch){
csi_send((unsigned char)ch);
}
char TERMIO_GetChar(void){
return (char)csi_receive();
}
/*************************************************************/
/* 串口初始化函数 */
/*************************************************************/
void sci_init(void) {
SCI0BD = D_BUSCLK_FREQ/16/D_SCI_BAUDRATE; // 设置SCI0波特率 busCLK/16/BAUDRATE;
SCI0CR1 = 0x00; //设置SCI0为正常模式,八位数据位,无奇偶校验 7:LOOPS 6:SCISWAI 5:RSRC 4:M 3:WAKE 2:ILT 1:PE 0:PT
SCI0CR2 = 0x0C; //允许收发数据,允许收发中断功能 7:TIE, 6:TCIE, 5:RIE, 4:ILIE, 3:TE, 2:RE, 1:RWU, 0:SBK
}
/**
* @brief 锁相环 初始化
* @param none
* @return none
*/
void pll_init(void) {
CPMUPROT = 0x26; //保护时钟配置寄存器
CPMUCLKS_PSTP = 0; //禁用PLL
CPMUCLKS_PLLSEL = 1; //选择PLL作为系统时钟源
CPMUOSC_OSCE = 1; //外部晶振使能
while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能
// BUSCLK = (PLLCLK / 2) 总线频率=(锁相环频率/2)
#if 1
//fVOC= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1)
CPMUSYNR = 0x07;
//CPMUREFDIV = 0x0F; // PLLCLK:16M BUSCLK:8M
CPMUREFDIV = 0x07; // PLLCLK:32M BUSCLK:16M
//CPMUREFDIV = 0x03; // PLLCLK:64M BUSCLK:32M
#endif
#if 0
//fVOC配置 fVOC = 2*fREF*(SYNDIV +1)
//CPMUSYNR = 0x45; // PLLCLK:48M BUSCLK:24M
//CPMUSYNR = 0x44; // PLLCLK:40M BUSCLK:20M
//CPMUSYNR = 0x43; // PLLCLK:32M BUSCLK:16M
//CPMUSYNR = 0x42; // PLLCLK:24M BUSCLK:12M
CPMUSYNR = 0x01; // PLLCLK:16M BUSCLK:8M
CPMUREFDIV = 0x81;//REFDIV基准分频器配置
#endif
CPMUPOSTDIV = 0x00; // PLL CLOCK = VCO CLOCK / (POSTDIV + 1)
_asm(nop);
_asm(nop);
CPMUPLL=0x10; //锁相环调频启用,用以减少噪音
while(CPMUFLG_LOCK == 0); //等待PLL稳定
CPMUPROT = 0x00; //关闭保护时钟
CPMUCLKS_PLLSEL = 1; //使能PLL
}
void pwm_init(void) {
// 1.PWMx工作模式设置, 0:8位模式,1:16位模式;
PWMCTL_CON01 = 0;
PWMCTL_CON23 = 0;
PWMCTL_CON45 = 0;
PWMCTL_CON67 = 0;
// 2.PWMx极性设置,0:低电平有效, 1:高电平有效;
PWMPOL_PPOL0 = 1;
PWMPOL_PPOL1 = 1;
PWMPOL_PPOL2 = 1;
PWMPOL_PPOL3 = 1;
PWMPOL_PPOL4 = 1;
PWMPOL_PPOL5 = 1;
PWMPOL_PPOL6 = 1;
PWMPOL_PPOL7 = 1;
// 3.PWMx对齐方式设置, 0:左对齐, 1:右对齐;
PWMCAE_CAE0 = 0;
PWMCAE_CAE1 = 1;
PWMCAE_CAE2 = 1;
PWMCAE_CAE3 = 1;
PWMCAE_CAE4 = 1;
PWMCAE_CAE5 = 1;
PWMCAE_CAE6 = 1;
PWMCAE_CAE7 = 1;
// 4.时钟A、时钟B分频系数设置
PWMPRCLK_PCKA = 0x06;
PWMPRCLK_PCKB = 0x06;
// 5.PWMx时钟源配置:
PWMCLKAB_PCLKAB0 = 0; // Clock A
PWMCLK_PCLK0 = 0;
PWMCLKAB_PCLKAB1 = 0; // Clock SA
PWMCLK_PCLK1 = 1;
PWMCLKAB_PCLKAB2 = 1; // Clock B
PWMCLK_PCLK2 = 0;
PWMCLKAB_PCLKAB3 = 1; // Clock SB
PWMCLK_PCLK3 = 1;
PWMCLKAB_PCLKAB4 = 0;
PWMCLK_PCLK4 = 0;
PWMCLKAB_PCLKAB5 = 0;
PWMCLK_PCLK5 = 0;
PWMCLKAB_PCLKAB6 = 0;
PWMCLK_PCLK6 = 0;
PWMCLKAB_PCLKAB7 = 0;
PWMCLK_PCLK7 = 0;
// 6.时钟SA,SB频率设置:
PWMSCLA = 10;
PWMSCLB = 20;
// 7.PWMx周期设置:
PWMPER0 = 100;
PWMPER1 = 100;
PWMPER2 = 100;
PWMPER3 = 100;
PWMPER4 = 100;
PWMPER5 = 100;
PWMPER6 = 100;
PWMPER7 = 100;
// 8.PWMx占空比设置
PWMDTY0 = 10;
PWMDTY1 = 20;
PWMDTY2 = 30;
PWMDTY3 = 40;
PWMDTY4 = 50;
PWMDTY5 = 60;
PWMDTY6 = 70;
PWMDTY7 = 80;
PWME_PWME0 = 1;
PWME_PWME1 = 1;
PWME_PWME2 = 1;
PWME_PWME3 = 1;
PWME_PWME4 = 1;
PWME_PWME5 = 1;
PWME_PWME6 = 1;
PWME_PWME7 = 1;
// PWME = 0xff;
}
void main(void) {
/* put your own code here */
DisableInterrupts;
pll_init();
sci_init();
pwm_init();
EnableInterrupts;
for(;;) {
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}