MP3模块应用
最近用51做了一边播放音乐一边拍打亮灯的按键的游戏机,涉及到MP3模块播放音乐和数码管的驱动,这里记录一下。
先放MP3的驱动
#define MP3_BUFF_LEN 10
uint8_t MP3_CMD_BUFF[MP3_BUFF_LEN];
uint16_t MP3_CheckSum(uint8_t *mp3_cmd)
{
uint16_t sum = 0;
uint8_t i;
for (i = 1; i < 7; i++) {
sum += mp3_cmd[i];
}
return -sum;
}
void MP3_set_Cmd_buff(uint8_t *mp3_cmd, uint8_t cmd, uint8_t feedback, uint16_t dat)
{
uint16_t checksum;
uint8_t i;
mp3_cmd[0] = 0X7E;
mp3_cmd[1] = 0XFF;
mp3_cmd[2] = 0X06;
mp3_cmd[3] = cmd;
mp3_cmd[4] = feedback;
mp3_cmd[5] = (uint8_t)(dat >> 8);
mp3_cmd[6] = (uint8_t)dat;
checksum = MP3_CheckSum(mp3_cmd);
mp3_cmd[7] = (uint8_t)(checksum >> 8);
mp3_cmd[8] = (uint8_t)checksum;
mp3_cmd[9] = 0xEF;
// for(i = 0;i<10;i++)
// {
// LOG("mp3_cmd[%d] = 0x%x\n",(uint16_t)i,(uint16_t)mp3_cmd[i]);
// }
}
//具体的指令直接调用这个函数输入就可以了,通过串口4发送给MP3模块
void MP3_CMD_Uart_Send(uint8_t cmd, uint8_t feedback, uint16_t dat)
{
MP3_set_Cmd_buff(MP3_CMD_BUFF, cmd, feedback, dat);
uart4_put(MP3_CMD_BUFF, MP3_BUFF_LEN);
}
//串口4的代码
bit busy4 = 0;
void Uart4Isr() interrupt 18
{
if (S4CON & 0x02) {
S4CON &= ~0x02;
busy4 = 0;
}
if (S4CON & 0x01) {
S4CON &= ~0x01;
}
}
void Uart4Init(void) // 9600bps@35.000MHz MP3模块要用9600比特率
{
P5_IO_QB(2);
P5_IO_QB(3);
P_SW2 = 0x04; // RXD4_2/P5.2, TXD4_2/P5.3
S4CON = 0x10;
S4CON &= 0xBF;
AUXR |= 0x04;
T2L = 0x8F;
T2H = 0xFD;
AUXR |= 0x10;
}
void uart4_puc(char dat)
{
while (busy4)
;
busy4 = 1;
S4BUF = dat;
}
void uart4_put(uint8_t *p, uint8_t len)
{
while (len--) {
uart4_puc(*p++);
}
}
再放数码管的驱动
typedef enum {
TM1637_A = 1 << 0,
TM1637_B = 1 << 1,
TM1637_C = 1 << 2,
TM1637_D = 1 << 3,
TM1637_E = 1 << 4,
TM1637_F = 1 << 5,
TM1637_G = 1 << 6,
TM1637_H = 1 << 7,
} TM1637_AG_E;
uint8_t TM1637_Write_Cmd(uint8_t byte)
{
uint8_t status = 0;
soft_i2c_Start();
soft_i2c_SendByte(byte);
status |= soft_i2c_WaitAck();
soft_i2c_Stop();
return status;
}
uint8_t TM1637_WriteDisplayData(uint8_t addr, uint8_t Ddata)
{
uint8_t status = 0;
soft_i2c_Start();
soft_i2c_SendByte(addr);
status |= soft_i2c_WaitAck();
status <<= 1;
soft_i2c_SendByte(Ddata);
status |= soft_i2c_WaitAck();
status <<= 1;
soft_i2c_Stop();
return status;
}
uint8_t TM1637_Key_Scan()
{
uint8_t status = 0;
uint8_t rxbuf = 0;
soft_i2c_Start();
soft_i2c_SendByte(TM1637_READ_KEY_DATA_CMD);
status |= soft_i2c_WaitAck();
status <<= 1;
rxbuf = soft_i2c_ReadByte(0);
soft_i2c_Stop();
return rxbuf;
}
uint8_t Key_Press_Check()
{
uint8_t KeyStatus;
KeyStatus = TM1637_Key_Scan();
if (KeyStatus != 0xff) {
LOG("****KEY SCAN ERROR****");
return 0;
} else {
LOG("****KEY SCAN SUCCESS****");
return KeyStatus;
}
}
/**位置0~5, 支持显示的符号数 0~9, ' ', '-', '.' */
void TM1637_DisplayNumber(uint8_t pos, uint8_t num)
{
if (pos > 5)
pos = 5;
if (num >= TM1637_CHARACTER_SUPPORT_COUNT)
num = TM1637_CHARACTER_SUPPORT_COUNT - 1;
switch (pos) {
case 0:
TM1637_WriteDisplayData(TM1637_SEG1_ADDR, TM1637_NUMBER[num]);
break;
case 1:
TM1637_WriteDisplayData(TM1637_SEG2_ADDR, TM1637_NUMBER[num]);
break;
case 2:
TM1637_WriteDisplayData(TM1637_SEG3_ADDR, TM1637_NUMBER[num]);
break;
case 3:
TM1637_WriteDisplayData(TM1637_SEG4_ADDR, TM1637_NUMBER[num]);
break;
case 4:
TM1637_WriteDisplayData(TM1637_SEG5_ADDR, TM1637_NUMBER[num]);
break;
case 5:
TM1637_WriteDisplayData(TM1637_SEG6_ADDR, TM1637_NUMBER[num]);
break;
default:
break;
}
}
void TM1637_Display_time(uint16_t time)
{
uint8_t timeArray[3] = {10, 10, 10};
TM1637_Write_Cmd(TM1637_DISPLAY_CMD);
TM1637_Write_Cmd(TM1637_DISPLAY_ON | TM1637_BRIGHTNESS_8);
timeArray[2] = time % 10;
timeArray[1] = time / 10 % 10;
timeArray[0] = time / 100 % 10;
TM1637_DisplayNumber(3, 0);
TM1637_DisplayNumber(4, timeArray[1]);
TM1637_DisplayNumber(5, timeArray[2]);
}
//模拟I2C的驱动 TM1637数据读取和写入都是从低位开始 要注意
void soft_i2c_Delay()
{
unsigned char i;
i = softI2cDelayT;
while (--i)
;
}
void soft_i2c_Start(void)
{
I2C_SDA_1();
I2C_SCL_1();
soft_i2c_Delay();
I2C_SDA_0();
soft_i2c_Delay();
I2C_SCL_0();
soft_i2c_Delay();
}
void soft_i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
/* 先发送字节的低位 */
for (i = 0; i < 8; i++)
{
if (_ucByte & 0x01)
{
I2C_SDA_1();
}
else
{
I2C_SDA_0();
}
soft_i2c_Delay();
I2C_SCL_1();
soft_i2c_Delay();
I2C_SCL_0();
// if (i == 7)
// {
// I2C_SDA_1(); // 释放总线
// }
_ucByte >>= 1; /* 左移一个bit */
// soft_i2c_Delay();
}
I2C_SDA_1(); // 释放总线
}
uint8_t soft_i2c_ReadByte(u8 ack)
{
uint8_t i;
uint8_t value;
/* 读到第1个bit为数据的bit1 */
// I2C_SDA_INPUT(); // set data input
soft_i2c_Delay();
value = 0;
for (i = 0; i < 8; i++)
{
value >>= 1;
I2C_SCL_1();
soft_i2c_Delay();
if (I2C_SDA_READ())
{
value |=0x80;
}
else
{
value|=0x00;
}
//I2C_SCL_1();
//soft_i2c_Delay();
I2C_SCL_0();
soft_i2c_Delay();
}
// I2C_SDA_OUTPUT(); // set data output
soft_i2c_Delay();
if (ack == 0)
soft_i2c_NAck();
else
soft_i2c_Ack();
return value;
}
uint8_t soft_i2c_WaitAck(void)
{
uint8_t re;
I2C_SDA_1(); /* CPU释放SDA总线 */
// I2C_SDA_INPUT(); //set data input
soft_i2c_Delay();
soft_i2c_Delay();
I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */
soft_i2c_Delay();
soft_i2c_Delay();
if (I2C_SDA_READ()) /* CPU读取SDA口线状态 */
{
re = 1;
}
else
{
re = 0;
}
I2C_SCL_0();
// I2C_SDA_OUTPUT(); //set data output
soft_i2c_Delay();
return re;
}
void soft_i2c_Stop(void)
{
// I2C_SCL_OUTPUT();
// I2C_SDA_OUTPUT();
/* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
I2C_SDA_0();
I2C_SCL_1();
soft_i2c_Delay();
I2C_SDA_1();
}