偶然在b站看到這個專案機械數碼管,正好手邊有個ESP8266模塊還有PCA9685就來做一下,
模型下載地址
目前就搞了一個數字,未來工廠3d列印太貴了

PCA9685
要先設定頻率暫存器才能有輸出,想設定頻率暫存器必須先把MODE1暫存器的SLEEP位置一,

void set_freq(float freq)
{
u16 prescale,oldmode,newmode;
float prescaleval;
unsigned int day_time = 0;
freq *= 0.92;
prescaleval = 25000000;
prescaleval /= 4096; //prescaleval=round(osc_cloc/4096/freq)-1;
prescaleval /= freq;
prescaleval -= 1;
prescale = floor(prescaleval + 0.5);
oldmode = I2C_Read_One_Byte(0x80, PCA9685_MODE1_reg);
newmode = (oldmode&0xEF) | 0x10;
I2C_Write_One_Byte(0x80, PCA9685_MODE1_reg, newmode);
I2C_Write_One_Byte(0x80, PCA9685_PRE_SCALE_reg, prescale);
I2C_Write_One_Byte(0x80, PCA9685_MODE1_reg, oldmode);
delay_ms(2);
I2C_Write_One_Byte(0x80, PCA9685_MODE1_reg, (oldmode | 0xa1));
}
ESP8266
ESP8266測驗
先連接esp8266到電腦,用串口助手發送命令檢測模塊的功能
#測驗模塊能否正常作業
AT
#設定模塊為sta模式
AT+CWMODE=1
#重啟試生效
AT+RST
#連接WiFi
AT+CWJAP="熱點名字","密碼"
#設定單路模式
AT+CIPMUX=0
時間API
我使用的是淘寶免費的api
#TCP連接
AT+CIPSTART="TCP","api.m.taobao.com",80
#發送71個字符
AT+CIPSEND=71
出現“>”可以發送指令

輸入GET命令,獲取時間:
GET http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp

#透傳模式開
AT+CIPMODE=1
#發送資料
AT+CIPSEND
esp8266退出透傳模式重新使能AT命令發送“+++”(注意取消串口助手的發送新行),實際連接單片機使用時出現不斷重啟的問題,檢查后發現應該時模塊的供電不夠導致的,
串口控制ESP8266
實際使用時發現還是不進入透傳模式更方便
char tcp_con[] = "AT+CIPSTART=\"TCP\",\"api.m.taobao.com\",80\r\n";
char send_comm[] = "AT+CIPSEND=71\r\n";
char get_comm[] = "GET http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp\r\n";
esp8266_init_time();
while(time_flag == NON_OK);
time_flag = NON_OK;
void esp8266_init_time()
{
esp8266_send(tcp_con);
delay_ms(100);
esp8266_send(send_comm);
delay_ms(100);
esp8266_send(get_comm);
delay_ms(100);
}
void esp8266_send(char* str)
{
uart4_send_str(str);
}
串口4接識訓傳的時間戳
每次串口接收到新行“\r\n”,接識訓沖區就從頭開始接收,根據實際得到的淘寶網回傳的字串格式,發現字串開頭是“+IPD”結尾是“CLOSED”,把這個當作幀頭幀尾查找,確定unix時間戳字符所在的位置并將其轉化成數值,
u8 day_hour = 0;
u8 day_min = 0;
u8 day_sec = 0;
void UART4_IRQHandler()
{
u8 res;
static int index = 0;
u8 counter = 0;
unsigned int multi = 1;
unsigned int day_time = 0;
if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)
{
res = USART_ReceiveData(UART4);
rxbuff[index] = res;
if((rxbuff[index] == '\n') && (rxbuff[index-1] == '\r'))
{
if((rxbuff[index-2] == 'D')&&(rxbuff[index-3] == 'E')&&(rxbuff[index-4] == 'S')&&(rxbuff[index-5] == 'O')&&(rxbuff[index-6] == 'L')&&(rxbuff[index-7] == 'C')&&(rxbuff[0] == '+'))
{
unix_time = 0;
multi = 1;
for(counter = 0;counter < 10;counter++)
{
unix_time += (rxbuff[111-counter] - 0x30) * multi;
multi = multi * 10;
}
day_time = unix_time % 86400;
day_hour = day_time / 3600 + 8;
day_min = (day_time % 3600) / 60;
day_sec = (day_time % 3600) % 60;
//day_hour = day_hour + 8;
//printf("%d:%2d:%2d\r\n", day_hour, day_min, day_sec);
time_flag = OK;
}
index = 0;
}
else
{
index++;
}
}
}
stm32f1串口發送
使用串口發送字串時,出現了第一個字符發送不出來的情況,
置零sr的tc位:
UART4->SR |= 0xBF;
或者讀取一下SR暫存器:
(void)UART4->SR;
定時器每秒鐘重繪時間每小時對時一次
#define CHECK_DURATION 3600
void TIM2_IRQHandler(void) //TIM3??
{
static u8 flag = 0;
static unsigned int counter = 0;
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //??TIM3????????
{
if(counter == CHECK_DURATION)
{
esp8266_init();
//while(time_flag == NON_OK);
time_flag = NON_OK;
counter = 0;
printf("TIME_SYNC\r\n");
}
else
{
if(day_sec == 59)
{
day_sec = 0;
if(day_min == 59)
{
day_min = 0;
if(day_hour == 23)
{
day_hour = 0;
}
else
{
day_hour++;
}
}
else
{
day_min++;
}
}
else
{
day_sec++;
}
counter++;
}
if(flag == 0)
{
GPIO_ResetBits(GPIOG,GPIO_Pin_13);
flag = ~flag;
}
else
{
GPIO_SetBits(GPIOG,GPIO_Pin_13);
flag = ~flag;
}
printf("%d:%2d:%2d\r\n", day_hour, day_min, day_sec);
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
如下圖可以得到正確的時間:

字符編碼
// A B C D E F G
char number[] = {0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 0xcd, 0x00, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, //0
0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, //1
0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, //2
0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, //3
0x99, 0x01, 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, //4
0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, //5
0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, //6
0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, //7
0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, //8
0xcd, 0x00, 0xcd, 0x00, 0x99, 0x01, 0x99, 0x01, 0xcd, 0x00, 0xcd, 0x00, 0xcd, 0x00}; //9
//在定時器中斷當中呼叫
void set_num(char num)
{
//A
I2C_Write_One_Byte(0x80, PCA9685_CH0_ON_L_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH0_ON_H_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH0_OFF_L_reg, number[num*14]);
I2C_Write_One_Byte(0x80, PCA9685_CH0_OFF_H_reg, number[num*14+1]);//199-0 cd-1
//delay_ms(500);
//B
I2C_Write_One_Byte(0x80, PCA9685_CH1_ON_L_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH1_ON_H_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH1_OFF_L_reg, number[num*14+2]);
I2C_Write_One_Byte(0x80, PCA9685_CH1_OFF_H_reg, number[num*14+3]);//199-0 cd-1
//delay_ms(500);
//C
I2C_Write_One_Byte(0x80, PCA9685_CH2_ON_L_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH2_ON_H_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH2_OFF_L_reg, number[num*14+4]);
I2C_Write_One_Byte(0x80, PCA9685_CH2_OFF_H_reg, number[num*14+5]);//199-0 cd-1
//delay_ms(500);
//D
I2C_Write_One_Byte(0x80, PCA9685_CH3_ON_L_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH3_ON_H_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH3_OFF_L_reg, number[num*14+6]);
I2C_Write_One_Byte(0x80, PCA9685_CH3_OFF_H_reg, number[num*14+7]);//199-0 cd-1
//delay_ms(500);
//E
I2C_Write_One_Byte(0x80, PCA9685_CH4_ON_L_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH4_ON_H_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH4_OFF_L_reg, number[num*14+8]);
I2C_Write_One_Byte(0x80, PCA9685_CH4_OFF_H_reg, number[num*14+9]);//199-0 cd-1
//delay_ms(500);
//F
I2C_Write_One_Byte(0x80, PCA9685_CH5_ON_L_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH5_ON_H_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH5_OFF_L_reg, number[num*14+10]);
I2C_Write_One_Byte(0x80, PCA9685_CH5_OFF_H_reg, number[num*14+11]);//199-0 cd-1
//delay_ms(500);
//G
I2C_Write_One_Byte(0x80, PCA9685_CH6_ON_L_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH6_ON_H_reg, 0x00);
I2C_Write_One_Byte(0x80, PCA9685_CH6_OFF_L_reg, number[num*14+12]);
I2C_Write_One_Byte(0x80, PCA9685_CH6_OFF_H_reg, number[num*14+13]);//199-0 cd-1
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300811.html
標籤:其他
