1、学习CH04示例程序,包括gpio.c和4个工程中的main.c。
main.c代码
#define GLOBLE_VAR
#include "includes.h" //包含总头文件
int main(void)
{
uint32_t mMainLoopCount;
uint8_t mFlag;
uint32_t mLightCount;
DISABLE_INTERRUPTS;
mMainLoopCount=0;
mFlag='A';
mLightCount=0;
ENABLE_INTERRUPTS;
printf("------------------------------------------------------\n");
for(;;)
{
mMainLoopCount++;
if (mMainLoopCount<=12888999) continue;
mMainLoopCount=0;
if (mFlag=='L')
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='A';
gpio_set(LIGHT_BLUE,LIGHT_ON);
printf(" LIGHT_BLUE:ON--\n");
}
else
{
mFlag='L';
gpio_set(LIGHT_BLUE,LIGHT_OFF);
printf(" LIGHT_BLUE:OFF--\n");
}
}
}
学习到的点
DISABLE_INTERRUPTS
和ENABLE_INTERRUPTS
:禁用和启用中断是嵌入式系统编程中的常见做法,用于保护关键代码段,防止在执行过程中被打断。这可以提高代码执行的原子性和一致性。for(;;)
无限循环和计数器mMainLoopCount
用于实现延时:使用简单的计数器来实现延时控制,是一种常见的时间控制方法。这里通过计数器达到一定值后才执行特定操作,使得程序有节奏地执行任务。if-else
判断mFlag
的状态,实现简单的状态机:使用标志位mFlag
控制灯的开关状态,可以看作是一个基本的有限状态机(Finite State Machine,FSM),用于管理系统的状态和行为。- 在关键操作(如变量初始化)前后禁用和启用中断:确保在对共享资源(如全局变量)进行操作时不会被中断打断,从而避免数据不一致和其他并发问题。
2、给出 gpio_set(LIGHT_RED,LIGHT_OFF); 语句中, LIGHT_RED和LIGHT_OFF的值是多少?贴出每一步的查找截图。
3、用直接地址编程方式,实现红绿蓝三灯轮流闪烁
//Uart部分用直接地址方式实现
#define GLOBLE_VAR
#include "includes.h" //Include the master header file
int main(void)
{
//uart register related addresses
volatile uint32_t* RCC_AHB2; //Address of GPIO port A clock enable register
volatile uint32_t* RCC_APB1; //Address of UART 2 clock enable register
volatile uint32_t* gpio_ptr; //Base address of GPIO port A
volatile uint32_t* uart_ptr; //Base address of UART 2 port
volatile uint32_t* gpio_mode; //Pin mode register address = port base address
volatile uint32_t* gpio_afrl; //GPIO alternate function low register
volatile uint32_t* uart_brr; //UART baud rate register address
volatile uint32_t* uart_isr; //UART interrupt and status register base address
volatile uint32_t* uart_cr1; //UART control register 1 base address
volatile uint32_t* uart_cr2; //UART control register 2 base address
volatile uint32_t* uart_cr3; //UART control register 3 base address
volatile uint32_t* uart_tdr; //UART transmit data register
uint16_t usartdiv; //Value to be assigned to BRR register
//Variable assignment
RCC_APB1=0x40021058UL; //UART clock enable register address
RCC_AHB2=0x4002104CUL; //Address of GPIO port A clock enable register
gpio_ptr=0x48000000UL; //Base address of GPIOA port
uart_ptr=0x40004400UL; //Base address of UART2 port
gpio_mode=0x48000000UL; //Pin mode register address = port base address
gpio_afrl=0x48000020UL; // GPIO alternate function low register
uart_cr1=0x40004400UL; //UART control register 1 base address
uart_brr=0x4000440CUL; // UART baud rate register address
uart_isr=0x4000441CUL; // UART interrupt and status register base address
uart_tdr=0x40004428UL; //UART transmit data register
uart_cr2=0x40004404UL; // UART control register 2 base address
uart_cr3=0x40004408UL; //UART control register 3 base address
//Disable all interrupts
DISABLE_INTERRUPTS;
//User peripheral module initialization
gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF); //Initialize red LED
gpio_init(LIGHT_GREEN,GPIO_OUTPUT,LIGHT_OFF); //Initialize green LED
gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_OFF); //Initialize blue LED
//uart_init(UART_User,115200); (lines 58-102)
//Enable GPIOA and UART2 clocks
*RCC_APB1|=(0x1UL<<17U); //UART2 clock enable
*RCC_AHB2 |=(0x1UL<<0U); //GPIOA clock enable
//Set GPIO port to alternate function
//First, clear D7, D6, D5, D4
*gpio_mode &= ~((0x3UL<<4U)|(0x3UL<<6U));
//Then set D7, D6, D5, D4 to 1010, setting PTA2, PTA3 to alternate function serial function.
*gpio_mode |=((0x2UL<<4U)|(0x2UL<<6U));
//Select pin port alternate function
//First, clear D15~D8
*gpio_afrl &= ~((0xFUL<<8U)|(0xFUL<<12U));
//Then set D15~D8 to 01110111, set PTA3, PTA2 pins to USART2_RX, USART2_TX respectively
*gpio_afrl=(((0x1UL<<8U)|(0x2UL<<8U)|(0x4UL<<8U))|((0x1UL<<12U)|(0x2UL<<12U)|(0x4UL<<12U)));
//Temporarily disable UART functionality, the UE-USART enable bit is at position 0 in control register 1.
//After clearing this bit, the USART prescaler and output will immediately stop and discard all current operations.
*uart_cr1 &= ~(0x1UL);
//Temporarily disable serial transmission and reception, control register 1's transmitter enable bit (D3), receiver enable bit (D2)
*uart_cr1 &= ~((0x1UL<<3U)|(0x1UL<<2U));
//Configure baud rate
if(*uart_cr1&(0x1UL<<15) == (0x1UL<<15))
usartdiv = (uint16_t)((SystemCoreClock/115200)*2);
else
usartdiv = (uint16_t)((SystemCoreClock/115200));
*uart_brr = usartdiv;
//Initialize control register and interrupt status register, clear flags
//Disable interrupts
*uart_isr = 0x0UL;
//Clear the two enable bits in control register 2. D14-LIN mode enable bit, D11-clock enable bit
*uart_cr2 &= ~((0x1UL<<14U)|(0x1UL<<11U));
//Clear the three enable bits in control register 3. D5 (SCEN) -smartcard mode enable bit,
//D3 (HDSEL) -half-duplex select bit, D1 (IREN) -IrDA mode enable bit
*uart_cr3 &= ~((0x1UL<<5U) | (0x1UL<<3U) |(0x1UL<<1U));
//Start serial transmission and reception
*uart_cr1 |= ((0x1UL<<3U)|(0x1UL<<2U));
//Enable UART functionality
*uart_cr1 |= (0x1UL<<0U);
//Enable module interrupts
//uart_enable_re_int(UART_User); Enable UART_User module receive interrupt function
//uart_enable_re_int() function implementation: ①Enable UART receive interrupt; ②Enable interrupt controller IRQ interrupt
*uart_cr1 |= (0x1UL<<5); //Set bit RXNEIE at position 5 in USART_CR1 register: generate USART interrupt when ORE=1 or RXNE=1 in USART_ISR register
NVIC_EnableIRQ(USART2_IRQn); //Enable interrupt controller USART2 interrupt
//Enable all interrupts
ENABLE_INTERRUPTS;
//Output a prompt to open the serial port tool on the serial update page
printf("Uart部分用直接地址方式实现\r\n");
}
4、用调用构件方式,实现红绿蓝的八种组合轮流闪烁
#define GLOBLE_VAR
#include "includes.h"
int main(void)
{
uint32_t mMainLoopCount;
uint8_t mFlag;
uint32_t mLightCount;
DISABLE_INTERRUPTS;
mMainLoopCount=0;
mFlag='B';
mLightCount=0;
gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_ON); //初始化红灯
ENABLE_INTERRUPTS;
printf("------------------------------------------------------\n");
for(;;)
{
mMainLoopCount++;
if (mMainLoopCount<=12888999) continue;
mMainLoopCount=0;
if (mFlag=='R')
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='G';
gpio_set(LIGHT_RED,LIGHT_ON);
printf("标志为R LIGHT_RED=%d ,LIGHT_ON = %d\n",LIGHT_RED,LIGHT_ON);
printf(" 红灯:ON--\n\n");
}
else if (mFlag=='G')
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='B';
gpio_set(LIGHT_RED,LIGHT_OFF);
gpio_set(LIGHT_GREEN,LIGHT_ON);
printf("标志为G LIGHT_GREEN=%d ,LIGHT_ON = %d\n",LIGHT_GREEN,LIGHT_ON);
printf(" 绿灯:ON--\n\n");
}
else if (mFlag=='B')
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='Y';
gpio_set(LIGHT_GREEN,LIGHT_OFF);
gpio_set(LIGHT_BLUE,LIGHT_ON);
gpio_set(LIGHT_RED,LIGHT_OFF);
printf("标志为B LIGHT_BLUE=%d ,LIGHT_ON = %d\n",LIGHT_BLUE,LIGHT_ON);
printf(" 蓝灯:ON--\n\n");
}
else if (mFlag=='Y')
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='P';
gpio_set(LIGHT_RED,LIGHT_ON);
gpio_set(LIGHT_BLUE,LIGHT_OFF);
gpio_set(LIGHT_GREEN,LIGHT_ON);
printf(" 黄灯:ON--\n\n");
}
else if (mFlag=='P')
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='C';
gpio_set(LIGHT_RED,LIGHT_ON);
gpio_set(LIGHT_GREEN,LIGHT_OFF);
gpio_set(LIGHT_BLUE,LIGHT_ON);
printf(" 紫灯:ON--\n\n");
}
else if (mFlag=='C')
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='W';
gpio_set(LIGHT_BLUE,LIGHT_ON);
gpio_set(LIGHT_RED,LIGHT_OFF);
gpio_set(LIGHT_GREEN,LIGHT_ON);
printf(" 青灯:ON--\n\n");
}
else if (mFlag=='W')
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='D';
gpio_set(LIGHT_BLUE,LIGHT_ON);
gpio_set(LIGHT_GREEN,LIGHT_ON);
gpio_set(LIGHT_RED,LIGHT_ON);
printf(" 白灯:ON--\n\n");
}
else if (mFlag=='D')
{
mLightCount++;
printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
mFlag='R';
gpio_set(LIGHT_GREEN,LIGHT_OFF);
gpio_set(LIGHT_BLUE,LIGHT_OFF);
gpio_set(LIGHT_RED,LIGHT_OFF);
printf(" 暗灯:ON--\n\n");
}
}
}