基于Tiva C模块,写一个交通灯控制程序,需要实现一下功能,绿灯亮1分钟后黄灯亮3秒钟紧接着红灯亮1分钟以此循环。运用了时钟及GPIO、中断系统、定时器、SSI四个单元模块。
时间: 2024-02-03 10:14:48 浏览: 79
用定时器编的交通灯程序.gxw
好的,下面是基于Tiva C模块的交通灯控制程序,需要实现绿灯亮1分钟后黄灯亮3秒钟紧接着红灯亮1分钟以此循环的功能。
首先,我们需要定义一些常量和变量,以及初始化GPIO、中断系统、定时器和SSI模块。这些代码可以写在main函数的开头。
```c
#include <stdint.h>
#include "inc/tm4c123gh6pm.h"
#define RED_LED GPIO_PIN_1
#define YELLOW_LED GPIO_PIN_2
#define GREEN_LED GPIO_PIN_3
volatile uint32_t g_ui32SysTickCount = 0;
void SysTickIntHandler(void)
{
g_ui32SysTickCount++;
}
void InitGPIO(void)
{
// Enable the GPIO port that is used for the on-board LED.
SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF;
// Do a dummy read to insert a few cycles after enabling the peripheral.
volatile uint32_t ui32Loop = SYSCTL_RCGC2_R;
// Set the direction as output, and enable the GPIO pin for the LED (PF1 and PF2).
GPIO_PORTF_DIR_R = RED_LED | YELLOW_LED | GREEN_LED;
GPIO_PORTF_DEN_R = RED_LED | YELLOW_LED | GREEN_LED;
}
void InitInterrupts(void)
{
// Enable processor interrupts.
__enable_irq();
// Set up the period for the SysTick timer.
SysTickPeriodSet(SysCtlClockGet() / 1000);
// Register the interrupt handler
SysTickIntRegister(SysTickIntHandler);
// Enable the SysTick timer.
SysTickEnable();
}
void InitTimer(void)
{
// Enable the timer peripheral.
SYSCTL_RCGCTIMER_R |= SYSCTL_RCGCTIMER_R1;
// Do a dummy read to insert a few cycles after enabling the peripheral.
volatile uint32_t ui32Loop = SYSCTL_RCGCTIMER_R;
// Configure Timer 1 as a periodic timer.
TIMER1_CTL_R &= ~TIMER_CTL_TAEN; // Disable Timer 1A.
TIMER1_CFG_R = TIMER_CFG_32_BIT_TIMER;
TIMER1_TAMR_R = TIMER_TAMR_TAMR_PERIOD;
TIMER1_TAILR_R = SysCtlClockGet() - 1; // Set the reload value to generate a 1 second interrupt.
TIMER1_IMR_R = TIMER_IMR_TATOIM; // Enable Timer 1A timeout interrupt.
TIMER1_CTL_R |= TIMER_CTL_TAEN; // Enable Timer 1A.
}
void InitSSI(void)
{
// Enable the SSI0 peripheral.
SYSCTL_RCGCSSI_R |= SYSCTL_RCGCSSI_R0;
// Do a dummy read to insert a few cycles after enabling the peripheral.
volatile uint32_t ui32Loop = SYSCTL_RCGCSSI_R;
// Configure the SSI0 pins for SPI master mode.
GPIO_PORTA_AFSEL_R |= GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
GPIO_PORTA_PCTL_R = (GPIO_PORTA_PCTL_R & ~0x00FFF000) + 0x00111000;
GPIO_PORTA_DEN_R |= GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
// Configure the SSI0 as a SPI master.
SSI0_CR1_R &= ~SSI_CR1_SSE; // Disable SSI0.
SSI0_CR1_R = 0; // Select Freescale SPI mode.
SSI0_CC_R = 0; // Use system clock.
SSI0_CPSR_R = 10; // Set the clock prescaler to 10 (for a 10 MHz SPI clock).
SSI0_CR0_R = SSI_CR0_SCR(0) | SSI_CR0_SPH | SSI_CR0_SPO | SSI_CR0_FRF_MOTO | SSI_CR0_DSS_8; // Configure the SPI clock and frame format.
SSI0_CR1_R |= SSI_CR1_SSE; // Enable SSI0.
}
```
接下来,我们需要实现一个函数来控制交通灯的状态。根据题目要求,绿灯亮1分钟后黄灯亮3秒钟紧接着红灯亮1分钟以此循环。因此,我们可以使用系统计时器来计算时间,并根据时间来控制交通灯状态。代码如下:
```c
void ControlTrafficLight(void)
{
while (1)
{
// Set the green LED on for 1 minute.
GPIO_PORTF_DATA_R = GREEN_LED;
uint32_t ui32StartTime = g_ui32SysTickCount;
while ((g_ui32SysTickCount - ui32StartTime) < 60000) {};
// Set the yellow LED on for 3 seconds.
GPIO_PORTF_DATA_R = YELLOW_LED;
ui32StartTime = g_ui32SysTickCount;
while ((g_ui32SysTickCount - ui32StartTime) < 3000) {};
// Set the red LED on for 1 minute.
GPIO_PORTF_DATA_R = RED_LED;
ui32StartTime = g_ui32SysTickCount;
while ((g_ui32SysTickCount - ui32StartTime) < 60000) {};
}
}
```
最后,在main函数中调用以上函数即可。
```c
int main(void)
{
// Initialize the system clock to 80 MHz.
SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
// Initialize the GPIO, interrupts, timer, and SSI modules.
InitGPIO();
InitInterrupts();
InitTimer();
InitSSI();
// Control the traffic light.
ControlTrafficLight();
return 0;
}
```
这个程序会不断循环控制交通灯状态,直到程序被停止。注意,在实现交通灯状态控制时,我们使用了系统计时器来计算时间。系统计时器每隔1毫秒触发一次中断,因此可以用来精确计算时间。在程序开头的SysTickIntHandler函数中,我们增加了一个全局变量g_ui32SysTickCount,用来记录系统计时器中断触发的次数(即时间)。
需要注意的是,以上代码只是一个简单的示例程序,实际应用中可能需要考虑更多的因素,例如交通流量等。同时,还应该考虑如何优化程序,以减少处理器负载和能耗。
阅读全文