This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C123GH6PM - UART 和 PWM 中断问题- IAR 工作平台

Guru**** 2350600 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/610436/tm4c123gh6pm---uart-and-pwm-interrupts-issue---iar-workbench

大家好、我正在尝试构建一个程序来使用 PWM 控制 LED RGB 强度、但有一个捕获、必须通过 Putty 使用串行通信(UART)输入强度值。 在这两种情况下、都必须使用中断。

没有编译错误、当程序在 launchpad 上运行时、它不会在 PuTTy 上显示任何内容(设置正确)、当程序暂停时、它会在 busfaultandler 或 falut 处理程序上运行。

如果您能给我讲一下问题是什么、我会很感激。

提前感谢。 密耳

该计划如下:

#include
#include
#include
#include
#include
#include "math.h"
#include "inc/hw_ints.h"
#include "inc/hw_timer.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.c"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/pwm.h"
#include "driverlib/sysctl.c"
#include "driverlib/sysctl.h"
#include "driverlib/Timer.c"
#include "driverlib/Timer.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "system_Device.h"

//变量全局变量
volatile int brimo、counter=0;
char cadena[8];
int numero=0;
volatile int active = 0;

void console (void)(空)

字符 c;
int 计数器=0;
numero=0;
// funcion para imprimir en la pantalla putty
while (计数器=0)

// Si se recive un caracter,este es leido y luego escrito en el transmisor。
//不是"eco" de lo enviado。
IF (UARTCharsAvail (UART0_BASE))

C= UARTCharGet (UART0_BASE);//Leo el Caracter
Cadena[numero]=c;//Lo guardo en la cadena
如果(c ='0')||(c ='1')||(c ='2')||(c ='3')||(c ='4')||(c ='5')||(c ='6')||(c ='7')|(c ='8')|='9'(c ='9')|='='='9'(c')|='='='='9'(c'(c'='9')|=1'(c')|=1'(c=1')

如果(c ='\r')

计数器=1;//Finalizo la cadena

numere++;
UARTCharPut (UART0_BASE、c);// Lomismo que rece lo transmite
}否则

numero=0;//Si no es un número reinicio la cadena
UARTprintf ("\n 错误- Brillo 不正确\n);
UARTprintf ("Ingres el numero de brillo seguido de la Tecla (enter)\n");




void 对话器(void)

int f、i;
int p;
Brillo=0;
//重构 la conversión ó n de caracues a numos reales。
f= numero-1;
对于(i=0 <f;i++)

如果(i ==0)
P = 1;
其他
P *= 10;
Brillo = brino +((((((int)cadena[f-1-i]-48)*p);// conversión a entero


UARTprintf ("\n\n");
UARTprintf ("\nBrillo elegido:%i\n"brillo);// Imprimo el valor de brillo

// Rutina de servicio de interruption (ISR) de PWM

空 PWM1IntHandler (空)

//
//清除 PWM1加载中断标志。 该标志在 PWM 时置1
//计数器重新加载。
//
PWMGenIntClear (PWM1_base、PWM_GEN_2、PWM_INT_CNT_LOAD);
PWMGenIntClear (PWM1_base、PWM_GEN_3、PWM_INT_CNT_LOAD);

//
//将占空比重置为0.1%周期。 请注意、64是
//周期的0.01%(64000个周期)。
//

PWMPulseWidthSet (PWM1_base、PWM_OUT_2、64);
PWMPulseWidthSet (PWM1_base、PWM_OUT_3、64);

ACTIVE = 1;

// Rutina de servicio de interrucion (ISR) de UART


空 UARTIntHandler (void){
uint32_t ui32Status;

ui32Status = UARTIntStatus (UART0_BASE、TRUE);// se Lee el Estado de la interrucion
//对所有的人来说,都是一个很好的选择
// genero la interrucion。

UARTIntClear (UART0_BASE、ui32Status);// se "limpian" o resetean los 位
//相应地是一个中断发生器。
ACTIVATE=1;// Aso que se activó UART

空 Iniciador (空)

//
//********* UART *********
//

// Habitilar GPIO 端口 a que se utiliza para UART0。
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);

//配置 Los pines 参数多路复用功能 UART0 en el Puerto A0 y A1。
GPIOPinConfigure (GPIO_PA0_U0RX);
GPIOPinConfigure (GPIO_PA1_U0TX);

//使用抗阻性 UART0参数进行波阻尼配置 el reloj。
SysCtlPeripheralEnable (SYSCTL_Periph_UART0);

// utilizar el oscilador de 16MHz interna como fuente de reloj UART。
UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC);

// Selucionar la función ó n alternativa (UART) para estos pasadores。
GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);

//初始化 el UART para la consola de E/S
UARTStdioConfig (0、115200、16000000);

//*********
//********* 时钟选择
//*********

// Seteo el clock
SysCtlClockSet (SYSCTL_SYSDIV_1_SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHz);

//*********
//********* PWM *********
//*********
unsigned long ulPeriod;
//
//将 PWM 时钟设置为系统时钟。
//
SysCtlPWMClockSet (SYSCTL_PWMDIV_1);

SysCtlPeripheralEnable (SYSCTL_Periph_PWM1);//Tiva Launchpad 有两个模块(0和1)。 模块1涵盖 LED 引脚
ulPeriod = SysCtlClockGet ()/250;//PWM 频率250Hz

//将 PF1、PF2、PF3引脚配置为 PWM
GPIOPinConfigure (GPIO_PF1_M1PWM5);
GPIOPinConfigure (GPIO_PF2_M1PWM6);
GPIOPinConfigure (GPIO_PF3_M1PWM7);
GPIOPinTypePWM (GPIO_PORTF_BASE、GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

//配置 PWM 选项
//PWM_GEN_2涵盖 M1PWM4和 M1PWM5
//PWM_GEN_3涵盖 M1PWM6和 M1PWM7

//
//将 PWM1配置为在不同步的情况下进行倒计数。
//
PWMGenConfigure (PWM1_base、PWM_GEN_2、PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
PWMGenConfigure (PWM1_base、PWM_GEN_3、PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);


//
//将 PWM 周期设置为250Hz。 以计算适当的参数
//使用以下公式:n =(1 / f)* SYSCLK。 其中 N 是
//函数参数、f 是所需的频率、SYSCLK 是
//系统时钟频率。
//在本例中、您得到:(1/250Hz)* 16MHz = 64000个周期。 请注意
//可以设置的最大周期为2^16。
//
//设置周期(以时钟节拍表示)
PWMGenPeriodSet (PWM1_base、PWM_GEN_2、ulPeriod);
PWMGenPeriodSet (PWM1_base、PWM_GEN_3、ulPeriod);


//启用 PWM 发生器
PWMGenEnable (PWM1_base、PWM_GEN_2);
PWMGenEnable (PWM1_base、PWM_GEN_3);

//打开输出引脚
PWMOutputState (PWM1_base、PWM_OUT_5_bit |PWM_OUT_6_bit|PWM_OUT_7_bit、true);

//
//******** GPIOF'*********
//

//
//启用用于板载 LED 的 GPIO 端口。
//
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);

//
//为 LED 启用 GPIO 引脚(PF1)。 将方向设置为输出、然后
//启用 GPIO 引脚以实现数字功能。
//
GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_1);

//
//为 LED 启用 GPIO 引脚(PF2)。 将方向设置为输出、然后
//启用 GPIO 引脚以实现数字功能。
//
GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_2);


//
//为 LED 启用 GPIO 引脚(PF3)。 将方向设置为输出、然后
//启用 GPIO 引脚以实现数字功能。
//
GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_3);


//
//********* HABILITACION DE INTERRUPCIONES DE PWM ********
//
//
//启用处理器中断。
//
IntMasterEnable();

//
//允许 PWM0产生中断。 此配置是针对完成的
//区分故障中断与其他 PWM1相关的中断。
//
PWMIntEnable (PWM1_base、PWM_INT_GEN_2);
PWMIntEnable (PWM1_base、PWM_INT_GEN_3);

//
//在 PWM0上启用 PWM0装载中断。
//
PWMGenIntTrigEnable (PWM1_base、PWM_GEN_2、PWM_INT_CNT_LOAD);
PWMGenIntTrigEnable (PWM1_base、PWM_GEN_3、PWM_INT_CNT_LOAD);

//
//在处理器(NVIC)上启用 PWM0中断。
//
IntEnable (INT_PWM1_2);
内部使能(INT_PWM1_3);

//
//启用 PWM0输出信号(PD0)。
//
PWMOutputState (PWM1_base、PWM_OUT_5_BIT、true);
PWMOutputState (PWM1_base、PWM_OUT_6_bit、true);
PWMOutputState (PWM1_base、PWM_OUT_7_bit、true);

//
//启用 PWM 发生器模块。
//
PWMGenEnable (PWM1_base、PWM_GEN_2);
PWMGenEnable (PWM1_base、PWM_GEN_3);

//*********
//********* HABILITACION DE INTERRUPCIONES UART 代码*****
//*********

IntMasterEnable();//处理器间的可用性中断
IntEnable (INT_UART0);// UART0的可用中断
// Habitilamos Generacion de interruciones a la acition de un caracter (RX) o cuando se
//生成接收器的非超时(RT)
// La interrucion a la Receivcion (RX) se genera cuando:
//-使用非汽车(CON FIFO 不稳定性)、
//- o cuando se alcanza o cuando se alcanza el nivel especificado en la FIFO
//(si la FIFO 复原)
UARTIntEnable (UART0_BASE、UART_INT_RX | UART_INT_RT);//


int main()

ACTIVE = 0;//Iniciizo que el SW2 se encuentra apagado
inicializador();//Inicializo las 变量、pueros、interruciones y clock
console();//eSCRIBE en pantalla
conversor();//reiza la conversión ó n de la cadena a enteros


// bucle Infiniband 到 interrupción 词
while (1)

如果(有效= 1)

有效= 0;
int 计数器=0;
UARTprintf ("inicio de PWM \n");
// Encendemos LED Verde con PWM
PWMPulseWidthSet (PWM1_base、PWM_OUT_7、brio);
SysCtlDelay((SysCtlClockGet()/(3*1000));

console();
conversor();



  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    通过应用"分裂与征服"策略来简化您的目标是否"很有意义"?   (此类策略称为"kiss"。)

    注意:我刚刚(非常)简单地看了一下您的代码-您知道每个 PWM 发生器都采用了特定的 MCU 引脚-从哪个引脚产生输出?   您的代码-相反-显示为将 LED 连接至 GPIO -不是由 PWM 发生器直接控制。

    例如-这里是(很久以前)代码-已知正常-由我的公司使用来从适当的 PWM 指定引脚生成 PWM 输出。   (并非所有引脚都支持 PWM!)

    无效
    PWMInit (空)


    ROM_SysCtlPeripheralEnable (SYSCTL_Periph_PWM0);
    //
    //使 PWM 引脚成为外设功能。
    //
    ROM_GPIOPinTypePWM (GPIO_PORTB_BASE、GPIO_PIN_6 | GPIO_PIN_7);   // 注意-这些引脚是我们的-不是您的!
    ROM_GPIOPinConfigure (GPIO_PB6_M0PWM0);
    ROM_GPIOPinConfigure (GPIO_PB7_M0PWM1);

    这两个"引脚配置"函数不会出现在代码中-它们应该-它们不应该出现吗?   (再次-我已经对您的代码进行了简要/快速扫描-这就是您的工作...)

    现在将我们的代码与您的代码进行比较:

    //启用用于板载 LED 的 GPIO 端口。
    //
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);

    //
    //为 LED 启用 GPIO 引脚(PF1)。 将方向设置为输出、然后
    //启用 GPIO 引脚以实现数字功能。
    //
    GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_1);   // 这可以很好地防止这个引脚被 PWM 控制-如果它(偶数)在具有 PWM 电势能力的范围内...

    //
    //为 LED 启用 GPIO 引脚(PF2)。 将方向设置为输出、然后
    //启用 GPIO 引脚以实现数字功能。
    //
    GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_2);

    ***请注意,LED 引脚(PF2)未按顺序进入 PWM 配置 (如您的上述代码所示)-这会使您的目的失败!

    在 MCU 手册的 PWM 部分中花费更多的时间/精力将有助于您更好地了解和遵守这些复杂 MCU 的"规则"。   同样、MCU 手册的一页或几页-包含在 PWM 部分-明确指定那些"连接"到 PWM 发生器的引脚!   不包含此类 PWM 列表的引脚-不是 PWM 可控的!   (由 PWM 发生器提供)

    就像现在一样-您的 PWM 系列被 UART "扣为人质"-可能是"UART"或"PWM Gen"或"两者都有过错!   而且-利用您创建的组合-您(甚至)如何开始了解" 在哪里以及如何"?

    我建议现在避免使用 UART -而是完全关注 PWM 发生器-并使其正常工作-从最简单/最简单的(即一个 PWM 通道到该三色 LED 的一种颜色)开始。   一旦您正确执行一种颜色-您可以转到第二种颜色-这种颜色(实际上)涉及的不仅仅是"更改""Source PWM Generator"(源 PWM 发生器)(即您添加新的 PWM 发生器)和将信号输出更改为第二个 LED Color Lead (色导联)。   (第三个也是如此。)

    一旦实现、您可以简单地使用 UART 进行实验-使其正常工作(自身)、并且仅尝试(随后)"将 UART 接收到的数据加入到 LED 颜色的选择中"。   (通过颜色"混合"@三色 LED 的变化实现。   该颜色的"混合"是通过每个 PWM 发生器的"占空比"的变化实现的-占空比越高-特定颜色越亮。)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    抱歉、"分裂与征服"是指什么?

    二十

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢、我将深入了解您所说的内容、并尝试使您的工作正常。 事情是、我必须使用 UART 或至少使用板载开关来实现它。

    二十

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    UART 程序自行运行。 我忘记澄清这一点。

    谢谢
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    无需悲伤-请"再次阅读"我的帖子。 (我已添加3倍) 在设置和配置中存在严重的代码错误。 PWM 发生器-显示更多时间和 MCU 手册。 请再次阅读-可能是两次-然后会更清楚...