本帖最后由 gaoyang9992006 于 2024-6-14 23:28 编辑
1、设计思路与方案结构
一般DSP收音机集成芯片都是I2C接口,彩色显示屏一般都是SPI接口。按键使用GPIO+中断实现。
因此本次使用开发板显示收音机功能结构如下:
通过开发板上的两个按键实现切换电台。
TFT彩屏与收音机模块采用杜邦线连接。
2、按键的实现
开发板上具备2个按键和2个LED灯珠,可以利用灯珠来学习按键,用于指示按键的状态。
按键的配置与中断可以参考标准库文件中提供的示例。
按键的使用需要配置按键所在的时钟使能,配置中断使能,设置IO模式为输入模式。
RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_GPIOA | RCC_AHB_PERIPH_GPIOB, ENABLE);
另外注意到
__RCC_GPIOB_CLK_ENABLE();
__RCC_GPIOA_CLK_ENABLE();
对应宏与上述函数式是一样的配置结果。
- void NVIC_Configuration(void)
- {
- __disable_irq();
- GPIOA_INTFLAG_CLR( 0xFFFF ); //clear GPIOA ALL INT FLAG
- NVIC_EnableIRQ(GPIOA_IRQn);
- __enable_irq();
- }
- //LED引脚配置
- GPIO_InitStructure.IT = GPIO_IT_NONE;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Pins = LED1_GPIO_PINS;
- GPIO_InitStructure.Speed= GPIO_SPEED_HIGH;
- GPIO_Init(LED1_GPIO_PORT,&GPIO_InitStructure);
- GPIO_WritePin(LED1_GPIO_PORT,LED1_GPIO_PINS,GPIO_Pin_SET);
-
- GPIO_InitStructure.Pins = LED2_GPIO_PINS;
- GPIO_Init(LED2_GPIO_PORT,&GPIO_InitStructure);
- GPIO_WritePin(LED2_GPIO_PORT,LED2_GPIO_PINS,GPIO_Pin_SET);
-
- //按键引脚配置
- __RCC_GPIOA_CLK_ENABLE();
- GPIO_InitStructure.IT = GPIO_IT_FALLING;
- GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
- GPIO_InitStructure.Pins = S1_GPIO_PINS;
- GPIO_Init(S1_GPIO_PORT,&GPIO_InitStructure);
- GPIO_InitStructure.Pins = S2_GPIO_PINS;
- GPIO_Init(S1_GPIO_PORT,&GPIO_InitStructure);
这样就可以完成按键的配置。
中断函数的实现是在一个interrupts_cw32f030.c文件中定义好了入口函数,只要完成函数体即可。
- void GPIOA_IRQHandler(void)
- {
- /* USER CODE BEGIN */
- if(REGBITS_GET(CW_GPIOA->ISR, GPIOx_ISR_PIN1_Msk) > 0)
- {
- Key1_flag = 1;
- Key2_flag = 0;
- //清除CW_GPIO中断标志
- GPIOA_INTFLAG_CLR(GPIOx_ICR_PIN1_Msk);
- }
- if(REGBITS_GET(CW_GPIOA->ISR, GPIOx_ISR_PIN2_Msk) > 0)
- {
- Key1_flag = 0;
- Key2_flag = 1;
- //清除CW_GPIO中断标志
- GPIOA_INTFLAG_CLR(GPIOx_ICR_PIN2_Msk);
- }
- /* USER CODE END */
- }
读取中断标志,判断操作,清除标志。
3、I2C的实现
I2C可以由软件实现,也可以由硬件实现
这里提供两种实现方式给大家参靠
- #include "IO_I2C.h"
- #if SOFTWARE_SPI_ENABLE
- void SDA_IO_DIR_OUTPUT(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.IT = GPIO_IT_NONE;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Pins = SDA_IO_PIN;
- GPIO_InitStructure.Speed= GPIO_SPEED_HIGH;
- GPIO_Init(SDA_IO_PORT,&GPIO_InitStructure);
- }
- void SDA_IO_DIR_INPUT(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.IT = GPIO_IT_NONE;
- GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
- GPIO_InitStructure.Pins = SDA_IO_PIN;
- GPIO_InitStructure.Speed= GPIO_SPEED_HIGH;
- GPIO_Init(SDA_IO_PORT,&GPIO_InitStructure);
- }
- void SCL_IO_DIR_OUTPUT(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.IT = GPIO_IT_NONE;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Pins = SCL_IO_PIN;
- GPIO_InitStructure.Speed= GPIO_SPEED_HIGH;
- GPIO_Init(SCL_IO_PORT,&GPIO_InitStructure);
- }
- void i2cBeginTransaction()
- {
- SDA_IO_DIR_OUTPUT();
- SCL_IO_DIR_OUTPUT();
- delay10us(1);
- SDA_IO_SET_HIGH();
- SCL_IO_SET_HIGH();
- SDA_IO_SET_LOW();
- }
- void i2cEndTransaction()
- {
- SDA_IO_DIR_OUTPUT();
- delay10us(1);
- SDA_IO_SET_LOW();
- SCL_IO_SET_HIGH();
- delay10us(1);
- SDA_IO_SET_HIGH();
- }
- void i2cAck()
- {
- SDA_IO_DIR_OUTPUT();
- delay10us(1);
- SDA_IO_SET_LOW();
- SCL_IO_SET_HIGH();
- SCL_IO_SET_LOW();
- }
- void i2cNack()
- {
- SDA_IO_DIR_OUTPUT();
- delay10us(1);
- SDA_IO_SET_HIGH();
- SCL_IO_SET_HIGH();
- SCL_IO_SET_LOW();
- }
- uint8_t i2cReceiveAck()
- {
- uint8_t ack;
- SDA_IO_DIR_INPUT();
- delay10us(1);
- SCL_IO_SET_HIGH();
- ack = SDA_IO_GET_VALUE();
- SCL_IO_SET_LOW();
- return ack;
- }
- void i2cWriteByte(uint8_t data)
- {
- SDA_IO_DIR_OUTPUT();
- delay10us(1);
- SCL_IO_SET_LOW();
- for (int i = 0; i < 8; i++)
- {
- if(0x80==(data & 0x80))
- {
- SDA_IO_SET_HIGH();
- }
- else
- {
- SDA_IO_SET_LOW();
- }
- SCL_IO_SET_HIGH();
- data = data << 1;
- SCL_IO_SET_LOW();
- }
- }
- uint8_t i2cReadByte(void)
- {
- uint8_t value = 0;
- SDA_IO_DIR_INPUT();delay10us(1);
- for (int i = 0; i < 8; i++)
- {
- SCL_IO_SET_HIGH();
- value = value << 1;
- if (SDA_IO_GET_VALUE())
- value = value | 1;
- SCL_IO_SET_LOW();
- }
- return value;
- }
- uint8_t KT_Byte_Read(uint8_t reg)
- {
- uint8_t dat=0;
- i2cBeginTransaction();
- i2cWriteByte(0x6A);
- i2cReceiveAck();
- i2cWriteByte(reg);
- i2cReceiveAck();
- i2cBeginTransaction();
- i2cWriteByte(0x6B);
- i2cReceiveAck();
- dat = i2cReadByte();
- i2cNack();
- i2cEndTransaction();
- return dat;
- }
- void KT_Byte_Write(uint8_t reg,uint8_t dat)
- {
- i2cBeginTransaction();
- i2cWriteByte(0x6A);
- i2cReceiveAck();
- i2cWriteByte(reg);
- i2cReceiveAck();
- i2cWriteByte(dat);
- i2cReceiveAck();
- i2cEndTransaction();
- }
- void KT_I2C_Init(void)
- {
- KT_I2C_SCL_CLK_ENABLE();
- KT_I2C_SDA_CLK_ENABLE();
- }
- #else
- void KT_I2C_Init(void)
- {
- KT_I2C_AFSCL;
- KT_I2C_AFSDA;
-
- GPIO_InitTypeDef GPIO_InitStructure;
- //I2C SCL SDA 复用
- GPIO_InitStructure.Pins = KT_I2C_SCL_GPIO_PIN;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
- GPIO_InitStructure.IT = GPIO_IT_NONE;
- GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
- GPIO_Init(KT_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
-
- GPIO_InitStructure.Pins = KT_I2C_SDA_GPIO_PIN;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
- GPIO_InitStructure.IT = GPIO_IT_NONE;
- GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
- GPIO_Init(KT_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
-
- I2C_InitTypeDef I2C_InitStruct;
- KT_I2C_ClkENx;
- //I2C初始化
- I2C_InitStruct.I2C_BaudEn = ENABLE;
- I2C_InitStruct.I2C_Baud = 0x05;//1MHz=(48000000/(8*(5+1))
- I2C_InitStruct.I2C_FLT = DISABLE;
- I2C_InitStruct.I2C_AA = DISABLE;
-
- KT_I2C_DeInit;
- I2C_Master_Init(KT_I2C,&I2C_InitStruct);//初始化模块
- I2C_Cmd(KT_I2C,ENABLE); //模块使能
- }
- uint8_t KT_Byte_Read(uint8_t u8Addr)
- {
- uint8_t dat;
- HAL_I2C_Mem_Read(KT_I2C,0x6A,u8Addr,&dat,1);
- return dat;
- }
- void KT_Byte_Write(uint8_t reg,uint8_t dat)
- {
- HAL_I2C_Mem_Write(KT_I2C,0x6A, reg, &dat, 1);
- }
- #endif
通过预编译中定义的宏来选择使用哪种。
4、SPI的实现
用于驱动TFT,推荐使用硬件实现。
应先对IO的复用功能进行选择,然后对IO进行配置,选择正确的IO模式,这里为推挽输出模式。最后对选择的SPI接口进行配置。
完成配置后并启用SPI接口,接下来就可以用相关写函数对TFT显示屏操作了。
- void SPI_Configuration(void)
- {
- __RCC_GPIOA_CLK_ENABLE();
- __RCC_GPIOB_CLK_ENABLE();
-
- PB13_AFx_SPI2SCK();
- PB15_AFx_SPI2MOSI();
-
- GPIO_InitTypeDef GPIO_InitStructure;
- //推挽输出
- GPIO_InitStructure.Pins = ST7735_CS_Pin;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
- GPIO_Init(ST7735_CS_GPIO_Port, &GPIO_InitStructure);
-
- GPIO_InitStructure.Pins = ST7735_DC_Pin;
- GPIO_Init(ST7735_DC_GPIO_Port, &GPIO_InitStructure);
-
- GPIO_InitStructure.Pins = ST7735_RST_Pin;
- GPIO_Init(ST7735_RST_GPIO_Port, &GPIO_InitStructure);
-
- GPIO_InitStructure.Pins = ST7735_SCK_Pin;
- GPIO_Init(ST7735_SCK_GPIO_Port, &GPIO_InitStructure);
-
- GPIO_InitStructure.Pins = ST7735_MOSI_Pin;
- GPIO_Init(ST7735_MOSI_GPIO_Port, &GPIO_InitStructure);
-
- SPI_InitTypeDef SPI_InitStructure;
- SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_TxOnly; //单工只发
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 主机模式
- SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 帧数据长度为8bit
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // 时钟空闲电平为高
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 第2个边沿采样
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 片选信号由SSI寄存器控制
- SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // 波特率为PCLK的4分频
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 最高有效位 MSB 收发在前
- SPI_InitStructure.SPI_Speed = SPI_Speed_Low; // 低速SPI
- SPI_Init(ST7735_SPI, &SPI_InitStructure);
- SPI_Cmd(ST7735_SPI, ENABLE);
- }
最后奉上完整的工程文件
演示视频看帖
https://bbs.21ic.com/icview-3382898-1-1.html
|