본문 바로가기
공부,일/Arm

pwm 실습

by fromnothing1 2021. 9. 6.

레지스터 설정 

 

PWM Mode Register
Register Name: PWM_MR

PREB = 1024

DIVB  = 128 

 

정도 하면 mck 가 48Mhz 임으로 0.043690667 마나 1번씩 가득찬다.

 

 

PWM Enable Register
Register Name: PWM_ENA

PWM_ENA = 0x01

CHID0 ,사용 

 

PWM Interrupt Enable Register
Register Name: PWM_IER

PWM_IER = 0x01 

 

CHID0  인터럽트 허용

 

 

PWM Channel Mode Register
Register Name: PWM_CMRx

CALG = 0 : 왼쪽정렬

CPOL = 0 : 출력은 0 에서 시작

 

 

PWM Channel Duty Cycle Register
Register Name: PWM_CDTYx

 

Only the first 16 bits (internal channel counter size) are significant.

- PWM_CDTYx 는 32bit 이지만 내부 카운터가 16bit 짜리라서 앞에 16bit 만 의미를 가진다. 

 

 

PWM Channel Period Register
Register Name: PWM_CPRDx

 

Only the first 16 bits (internal channel counter size) are significant.

- PWM_CPRDx 는 32bit 이지만 내부 카운터가 16bit 짜리라서 앞에 16bit 만 의미를 가진다. 

 

pin 설정

PWM0 는 Peripheral B 이다. 

 

pin 예제를 보면 Line 20 ~ 23 번이 Peripheral B 를 사용하고 있다.  때문에 예시의 빨간 네모 안이 F 인 레지스터를 set 해주면 pin 출력 준비가 완료 된다. 

 

PIO_PDR 
PIO_ODR
PIO_IFDR
PIO_CODR
PIO_MDDR
PIO_PUDR
PIO_BSR
PIO_OWDR

#include <AT91SAM7S256.h>
#define BOARD_MCK 48000000

AT91S_PWMC* AT91PS_PWMC1 = (AT91S_PWMC*)0xFFFCC000;
AT91S_PWMC_CH* AT91PS_PWMC_CH0 = (AT91S_PWMC_CH*)0xFFFCC200;

void UTIL_Loop(unsigned int loop)
{
	while (loop--);
}
void UTIL_WaitTimeInMs(unsigned int mck, unsigned int time_ms)
{
	register unsigned int i = 0;
	i = (mck / 1000) * time_ms;
	i = i / 3;
	UTIL_Loop(i);
}



void Pwm_Init(void)
{
	*AT91C_PMC_PCER = 1 << AT91C_ID_PWMC;		// PWM 장치에 클럭 공급

	// pin setting
	*AT91C_PIOA_PDR = 1;
	*AT91C_PIOA_ODR = 1;
	*AT91C_PIOA_IFDR = 1;
	*AT91C_PIOA_CODR = 1;
	*AT91C_PIOA_MDDR = 1;
	*AT91C_PIOA_PPUDR = 1;
	*AT91C_PIOA_ASR = 1;
	*AT91C_PIOA_OWDR = 1;

	// CLKA 를 200kHz로 설정   48Mhz / 8 / 30 
	*AT91C_PWMC_MR = (30 << 0) | (3 << 8);
	AT91PS_PWMC_CH0->PWMC_CPRDR = 600;
	// CLKA 클럭을 사용, left aligned, low level start, CUPD modify duty cycle
	// clkA 사용 , 왼쪽 정렬, low level 시작 , duty update
	*AT91C_PWMC_CH0_CMR = 11 & (~(0x1 << 8)) & (~(0x1 << 9)) & (~(0x1 << 10));
	AT91PS_PWMC_CH0->PWMC_CDTYR = 2;
	return;
}

int main(void)
{
	//volatile unsigned int delay;
	//int Num = 1;
	Pwm_Init();
	// pwm 시작
	AT91PS_PWMC1->PWMC_ENA = 0x01;

	while (1)
	{
		*AT91C_PWMC_CH0_CMR &= (~(0x1 << 10));
		AT91PS_PWMC_CH0->PWMC_CDTYR = 2;

		UTIL_WaitTimeInMs(BOARD_MCK, 10000);

		*AT91C_PWMC_CH0_CMR &= (~(0x1 << 10));
		AT91PS_PWMC_CH0->PWMC_CDTYR = 599;



	}
	return 0;
}
#include <AT91SAM7S256.h>
#define BOARD_MCK 48000000

// my pwm 

AT91S_PWMC* AT91PS_PWMC1 = (AT91S_PWMC*)0xFFFCC000;
AT91S_PWMC_CH* AT91PS_PWMC_CH0 = (AT91S_PWMC_CH*)0xFFFCC200;
AT91S_PWMC_CH* AT91PS_PWMC_CH1 = (AT91S_PWMC_CH*)0xFFFCC220;

void UTIL_Loop(unsigned int loop)
{
	while (loop--);
}
void UTIL_WaitTimeInMs(unsigned int mck, unsigned int time_ms)
{
	register unsigned int i = 0;
	i = (mck / 1000) * time_ms;
	i = i / 3;
	UTIL_Loop(i);
}



void Pwm_Init(void)
{
	*AT91C_PMC_PCER = 1 << AT91C_ID_PWMC;		// PWM 장치에 클럭 공급

	// pin setting
	*AT91C_PIOA_PDR = 1|(1<<1);
	//*AT91C_PIOA_ODR = 1;
	*AT91C_PIOA_IFDR = 1 | (1 << 1);
	//*AT91C_PIOA_CODR = 1;
	//*AT91C_PIOA_MDDR = 1;
	*AT91C_PIOA_PPUDR = 1 | (1 << 1);
	*AT91C_PIOA_ASR = 1| (1 << 1);
	//*AT91C_PIOA_OWDR = 1;

	// CLKA 를 200kHz로 설정   48Mhz / 8 / 30 
	*AT91C_PWMC_MR = (30 << 0) | (3 << 8);

	// ch 0 설정 
	AT91PS_PWMC_CH0->PWMC_CPRDR = (unsigned short)600;
	// CLKA 클럭을 사용, left aligned, low level start, CUPD modify duty cycle
	// clkA 사용 , 왼쪽 정렬, low level 시작 , duty update
	*AT91C_PWMC_CH0_CMR = 11 & (~(0x1 << 8)) & (~(0x1 << 9)) & (~(0x1 << 10));
	AT91PS_PWMC_CH0->PWMC_CDTYR = (unsigned short)598;

	// ch 1 설정
	AT91PS_PWMC_CH1->PWMC_CPRDR = (unsigned short)600;
	// CLKA 클럭을 사용, left aligned, low level start, CUPD modify duty cycle
	// clkA 사용 , 왼쪽 정렬, low level 시작 , duty update
	*AT91C_PWMC_CH1_CMR = 11 & (~(0x1 << 8)) & (~(0x1 << 9)) & (~(0x1 << 10));
	AT91PS_PWMC_CH1->PWMC_CDTYR = (unsigned short)2;



	return;
}

int main(void)
{
	//volatile unsigned int delay;
	//int Num = 1;
	Pwm_Init();
	// pwm 시작
	AT91PS_PWMC1->PWMC_ENA = 0x01;

	while (1)
	{
		//*AT91C_PWMC_CH0_CMR &= (~(0x1 << 10));
		//AT91PS_PWMC_CH0->PWMC_CDTYR = 2;

		//UTIL_WaitTimeInMs(BOARD_MCK, 1000);

		//*AT91C_PWMC_CH0_CMR &= (~(0x1 << 10));
		//AT91PS_PWMC_CH0->PWMC_CDTYR = 599;

		//UTIL_WaitTimeInMs(BOARD_MCK, 1000);

	}
	return 0;
}

'공부,일 > Arm' 카테고리의 다른 글

jtag 사용하기  (0) 2021.10.05
GPIO 다루기  (0) 2021.09.06
pwm datasheet 분석  (0) 2021.09.06
mamory map & LED 켜기  (0) 2021.09.06
uart  (0) 2021.09.02

댓글