本帖最后由 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
|