Hi, I'm trying to make a code about making a PWM without using the Tivaware libraries.
However, there were no PWM detected when I tested with my oscilloscope.
Here's the code below. Can somebody tell what is wrong and what needs to be added?
#include <stdbool.h>
#include <stdint.h>
#include "My_headers\tm4c123bh6pm.h"
#include "My_headers\hw_types.h"
#define BIT0 (0x0001u)
#define BIT1 (0x0002u)
#define BIT2 (0x0004u)
#define BIT3 (0x0008u)
#define BIT4 (0x0010u)
#define BIT5 (0x0020u)
#define BIT6 (0x0040u)
#define BIT7 (0x0080u)
#define BIT8 (0x0100u)
#define BIT9 (0x0200u)
#define BITA (0x0400u)
#define BITB (0x0800u)
#define BITC (0x1000u)
#define BITD (0x2000u)
#define BITE (0x4000u)
#define BITF (0x8000u)
void SW_Delay(volatile unsigned long Delay_t){
Delay_t *= 1000;
while(Delay_t--);
}
void RCC_CLK_SET(int RCC_BIT){
uint32_t ui32Delay, ui32RCC, ui32RCC2;
//
// Get the current value of the RCC and RCC2 registers.
//
ui32RCC = SYSCTL_RCC_R;
ui32RCC2 = SYSCTL_RCC2_R;
//
// Bypass the PLL and system clock dividers for now.
//
ui32RCC |= SYSCTL_RCC_BYPASS;
ui32RCC &= ~(SYSCTL_RCC_USESYSDIV);
ui32RCC2 |= SYSCTL_RCC2_BYPASS2;
//
// Write the new RCC value.
//
SYSCTL_RCC_R = ui32RCC;
SYSCTL_RCC2_R = ui32RCC2;
//
// See if the oscillator needs to be enabled.
//
if((ui32RCC & SYSCTL_RCC_MOSCDIS) && !(RCC_BIT & SYSCTL_RCC_MOSCDIS))
{
//
// Make sure that the required oscillators are enabled. For now, the
// previously enabled oscillators must be enabled along with the newly
// requested oscillators.
//
ui32RCC &= (~SYSCTL_RCC_MOSCDIS | (RCC_BIT & SYSCTL_RCC_MOSCDIS));
//
// Write the new RCC value.
//
SYSCTL_RCC_R = ui32RCC;
//
// Wait for a bit, giving the oscillator time to stabilize. The number
// of iterations is adjusted based on the current clock source; a
// smaller number of iterations is required for slower clock rates.
//
if(((ui32RCC2 & SYSCTL_RCC2_USERCC2) &&
(((ui32RCC2 & SYSCTL_RCC2_OSCSRC2_M) == SYSCTL_RCC2_OSCSRC2_30) ||
((ui32RCC2 & SYSCTL_RCC2_OSCSRC2_M) ==
SYSCTL_RCC2_OSCSRC2_32))) ||
(!(ui32RCC2 & SYSCTL_RCC2_USERCC2) &&
((ui32RCC & SYSCTL_RCC_OSCSRC_M) == SYSCTL_RCC_OSCSRC_30)))
{
//
// Delay for 4096 iterations.
//
SW_Delay(4096);
}
else
{
//
// Delay for 524,288 iterations.
//
SW_Delay(524288);
}
}
//
// Set the new crystal value and oscillator source. Because the OSCSRC2
// field in RCC2 overlaps the XTAL field in RCC, the OSCSRC field has a
// special encoding within RCC_BIT to avoid the overlap.
//
ui32RCC &= ~(SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M);
ui32RCC |= RCC_BIT & (SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M);
ui32RCC2 &= ~(SYSCTL_RCC2_USERCC2 | SYSCTL_RCC2_OSCSRC2_M);
ui32RCC2 |= RCC_BIT & (SYSCTL_RCC2_USERCC2 | SYSCTL_RCC_OSCSRC_M);
ui32RCC2 |= (RCC_BIT & 0x00000008) << 3;
//
// Write the new RCC value.
//
SYSCTL_RCC_R = ui32RCC;
SYSCTL_RCC2_R = ui32RCC2;
//
// Wait for a bit so that new crystal value and oscillator source can take
// effect.
//
SW_Delay(16);
//
// Set the PLL configuration.
//
ui32RCC &= ~SYSCTL_RCC_PWRDN;
ui32RCC |= RCC_BIT & SYSCTL_RCC_PWRDN;
ui32RCC2 &= ~SYSCTL_RCC2_PWRDN2;
ui32RCC2 |= RCC_BIT & SYSCTL_RCC2_PWRDN2;
//
// Clear the PLL lock interrupt.
//
SYSCTL_MISC_R = SYSCTL_IMC_PLLLIM;// 0x040 problem
//
// Write the new RCC value.
//
if(ui32RCC2 & SYSCTL_RCC2_USERCC2)
{
SYSCTL_RCC2_R = ui32RCC2;
SYSCTL_RCC_R = ui32RCC;
}
else
{
SYSCTL_RCC_R = ui32RCC;
SYSCTL_RCC2_R = ui32RCC2;
}
//
// Set the requested system divider and disable the appropriate
// oscillators. This value is not written immediately.
//
ui32RCC &= ~(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
SYSCTL_RCC_MOSCDIS);
ui32RCC |= RCC_BIT & (SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
SYSCTL_RCC_MOSCDIS);
ui32RCC2 &= ~(SYSCTL_RCC2_SYSDIV2_M);
ui32RCC2 |= RCC_BIT & SYSCTL_RCC2_SYSDIV2_M;
if(RCC_BIT & SYSCTL_RCC2_DIV400)
{
ui32RCC |= SYSCTL_RCC_USESYSDIV;
ui32RCC2 &= ~(SYSCTL_RCC_USESYSDIV);
ui32RCC2 |= RCC_BIT & (SYSCTL_RCC2_DIV400 | SYSCTL_RCC2_SYSDIV2LSB);
}
else
{
ui32RCC2 &= ~(SYSCTL_RCC2_DIV400);
}
//
// See if the PLL output is being used to clock the system.
//
if(!(RCC_BIT & SYSCTL_RCC_BYPASS))
{
//
// Wait until the PLL has locked.
//
for(ui32Delay = 32768; ui32Delay > 0; ui32Delay--)
{
if(SYSCTL_RIS_R & SYSCTL_IMC_PLLLIM)
{
break;
}
}
//
// Enable use of the PLL.
//
ui32RCC &= ~(SYSCTL_RCC_BYPASS);
ui32RCC2 &= ~(SYSCTL_RCC2_BYPASS2);
}
//
// Write the final RCC value.
//
SYSCTL_RCC_R = ui32RCC;
SYSCTL_RCC2_R = ui32RCC2;
//
// Delay for a little bit so that the system divider takes effect.
//
SW_Delay(16);
}
void PWMCLKSet(int PWM_BIT){ //Set the PWM clock to the system clock.
//
// Check that there is a PWM block on this part.
//
ASSERT(SYSCTL_DC1_R & (SYSCTL_DC1_PWM0 | SYSCTL_DC1_PWM1));
//
// Set the PWM clock configuration into the run-mode clock configuration
// register.
//
SYSCTL_RCC_R = (SYSCTL_RCC_R &
~(SYSCTL_RCC_USEPWMDIV | SYSCTL_RCC_PWMDIV_M) | PWM_BIT);
//Clear SYSCTL_RCC_R [20:17] bit (USEPWMDIV, PWMDIV)
//Then OR PWM_BIT to fill [20:17] bit(USEPWMDIV, PWMDIV)
}
void PWM_Module_Enable(int Enable){
SYSCTL_RCGCPWM_R |= Enable;
//PWM Run Mode Clock Gating Control Register
}
void GPIO_Gate_Control(int GPIO_BIT){
SYSCTL_RCGCGPIO_R |= GPIO_BIT;
SYSCTL_RCGC2_R |= GPIO_BIT;
}
void GPIO_B_PWM_SET(int PWM_BIT){
SW_Delay(5);
// Enable the GPIO pin for the LED (PF3). Set the direction as output, and
// enable the GPIO pin for digital function.
//
GPIO_PORTB_DIR_R |= PWM_BIT | BIT7; // Select as Output
GPIO_PORTB_AFSEL_R |= PWM_BIT; //Alternative Function Select
GPIO_PORTB_DEN_R |= PWM_BIT | BIT7; // Enable the GPIO pin for digital function.
GPIO_PORTB_ODR_R &= 0; //clear GPIOODR, ODR Disable
GPIO_PORTB_PCTL_R |= 0x4000000; //GPIO Port Control Register PCM6 => M0PWM0
GPIO_PORTB_DATA_R &= ~(BIT7); //Set PB7 to GND
}
void PWM0CTL(int LOAD, int CMPA, int CMPB){
PWM0_CTL_R = 0x6; //Count Down Mode,
PWM0_0_CTL_R = 0x06;
//Debug Mode : counter always run
//Disable PWM block
PWM0_0_GENA_R = 0x8C; //PWM0GENA Register,
//Comparator B Down and Up do nothing
//Comparator A Down Drive pwmA low
//Comparator A Up drive do nothing
//Counter = LOAD Drive pwmA High
//Counter = 0 Do nothing
PWM0_0_GENB_R = 0x80C;//PWM0GENB Register,
//Comparator B Down Drive pwmB Low.
//Comparator B Up Drive do nothing
//Comparator A Down and Up do nothing
//Counter = LOAD Drive pwmB High
//Counter = 0 Do nothing
PWM0_0_LOAD_R = LOAD; //LOAD Setting
PWM0_0_CMPA_R = CMPA;//Compare A
PWM0_0_CMPB_R = CMPB;//Compare B
SW_Delay(10);
PWM0_CTL_R |= 0x1; //Now enable PWM block
PWM0_0_CTL_R |= 0x1;
//Start the timers in PWM generator 0
}
void PWM0ENABLE(int PWM_EN){
PWM0_ENABLE_R |= 0x1;
//pwmA' , pwmB' output enable to MnPWMn
}
int main(void) {
RCC_CLK_SET(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_XTAL_16MHZ | SYSCTL_RCC_PWRDN |
SYSCTL_RCC_BYPASS | SYSCTL_RCC_OSCSRC_MAIN);
// Set the PWM
SET_PWM0_GPIO_B();
LED();
}