1. 程式人生 > >STM32F103的數碼管顯示(1)

STM32F103的數碼管顯示(1)

先來tm1629數碼管驅動,網上看了一大堆,主要是共陰極的居多,共陰極操作簡單,控制的數碼管較少,共陽極的控制的數碼管多,可是需要轉換轉換

 

TM16290.H

#ifndef __TM1629_H
#define __TM1629_H

#define TM1_STB_PIN GPIO_Pin_0
#define TM1_STB_PORT GPIOF

#define TM1_DIO_PIN GPIO_Pin_2
#define TM1_DIO_PORT GPIOF

#define TM1_CLK_PIN GPIO_Pin_1
#define TM1_CLK_PORT GPIOF

#define TM1_STB_H GPIO_SetBits(TM1_STB_PORT, TM1_STB_PIN)
#define TM1_STB_L GPIO_ResetBits(TM1_STB_PORT, TM1_STB_PIN)
#define TM1_DIO_H GPIO_SetBits(TM1_DIO_PORT, TM1_DIO_PIN)
#define TM1_DIO_L GPIO_ResetBits(TM1_DIO_PORT, TM1_DIO_PIN)
#define TM1_CLK_H GPIO_SetBits(TM1_CLK_PORT, TM1_CLK_PIN)
#define TM1_CLK_L GPIO_ResetBits(TM1_CLK_PORT, TM1_CLK_PIN)

#define READ_TM1_DIO GPIO_ReadInputDataBit(TM1_DIO_PORT, TM1_DIO_PIN)

/****************************public*********************************************************/
void tm1629a_gpio_init(void); //tm1629a埠初始化,推輓輸出
void tm1629_init(void); //tm1629晶片初始化程式

/****************************private*********************************************************/

void tm1629SendByte(unsigned char data); //序列模式 MCU一次輸出8個bit
void tm1629SendCmd(unsigned char cmd); //寫命令

void tm1639_write(unsigned char *data );//開啟TM1629並顯示指定的資料
void write_tm1639_off(unsigned char *data );//關閉TM1629顯示

void convert(unsigned char SrcNum, unsigned char *pDst , unsigned char seg, unsigned char dot);//共陽數碼管資料格式轉換 0~9轉換
void convert2(unsigned char SrcNum, unsigned char *pDst , unsigned char seg); //共陽數碼管資料格式轉換 特殊格式轉換

#endif

 

TM1629.C

#include "tm1629.h"
#include"stm32f10x.h" //只要呼叫庫函式,就需要新增此標頭檔案
#include"delay.h"

/****************************************************
*****************************************************
***********************public************************
*****************************************************
****************************************************/
/*tm1629埠初始化,3個埠都是推輓輸出*/
void tm1629a_gpio_init(void){
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); //使能PF埠時鐘

  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //TM1的STB挽輸出
  GPIO_InitStructure.GPIO_Pin=TM1_STB_PIN;
  GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
  GPIO_Init(TM1_STB_PORT, &GPIO_InitStructure); 

  GPIO_InitStructure.GPIO_Pin=TM1_DIO_PIN; //TM1的DIO推輓輸出
  GPIO_Init(TM1_DIO_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin=TM1_CLK_PIN; //TM1的CLK推輓輸出
  GPIO_Init(TM1_CLK_PORT, &GPIO_InitStructure);
}

/*啟動tm1629必須有一個啟動模式*/
void tm1629_init(void){
  TM1_CLK_H;
  TM1_DIO_H;
  TM1_STB_H;
  tm1629SendCmd(0x03); //寫TM1629顯示模式
  tm1629SendCmd(0x40); //寫資料到顯示暫存器的方式採用地址自動加一
  tm1629SendCmd(0x88); //開顯示,亮度可以通過改變低三位調節
}

 

 

/****************************************************
*****************************************************
***********************private***********************
*****************************************************
****************************************************/

/*序列模式 在時鐘的上升沿通過MCU向LED驅動IC——TM16xx寫資料 */
void tm1629SendByte(unsigned char dat){
  unsigned char i;
  TM1_STB_L;//保證“STB”為低電平,程式不依賴於之前埠的狀態;保證程式在實際執行中不會出現“埠迷失”
  for(i=0;i<8;i++)
  {
    TM1_CLK_L; //clk置低,等待發送資料
    if((dat & 0x01) == 0x01){ //傳送最高位給DI
    TM1_DIO_H; //需要傳送的資料的低位為“1”,則把“DIO”置高
  }
  else{
    TM1_DIO_L; //需要傳送的資料的低位為“0”,則把“DIO”置零
  }
  delay_ms(1);
  TM1_CLK_H; //送時鐘的上升沿
  dat >>= 1; //準備送下一個BIT
  //delay_ms(1);
  }
}

/*寫命令*/
void tm1629SendCmd(unsigned char cmd){
  TM1_STB_H;
  TM1_CLK_H;
  TM1_DIO_H; //通訊開始前通訊埠全部初始化為“1”
  delay_ms(2);
  TM1_STB_L; //片選(低電平)
  tm1629SendByte(cmd);
  TM1_STB_H;
}

 

/*開啟TM1629並顯示指定的資料*/
void tm1639_write(unsigned char *data ){
  unsigned char i=0;

  TM1_STB_H;
  tm1629SendByte(0x40); //傳資料設定命令,設定採用地址自動加一方式顯示資料
  TM1_STB_H;
  tm1629SendByte(0xc0); //傳送起始地址,地址命令傳完後,“STB”保持為0繼續傳需要顯示的資料
  for(i=0;i<16;i++) //在連續顯示的資料過程彙總,“STB”一直保持為0,
  {
tm1629SendByte(data[i]);
}
TM1_STB_H; //傳送完所有的顯示資料後(最多14BYTE),將STB置1
tm1629SendByte(0x88);//0x8f //開顯示,脈衝寬度為1/16 這個是最低的脈衝寬度
TM1_STB_H;
}

/*關閉TM1629顯示*/
void write_tm1639_off(unsigned char *data ){
unsigned char i=0;

TM1_STB_H;
tm1629SendByte(0x40); //傳資料設定命令,設定採用地址自動加一方式顯示資料
TM1_STB_H;
tm1629SendByte(0xc0); //傳送起始地址,地址命令傳完後,“STB”保持為0繼續傳需要顯示的資料
for(i=0;i<16;i++)
{
tm1629SendByte(data[i]);
}
TM1_STB_H;
tm1629SendByte(0x87); //關顯示,脈衝寬度為14/16
TM1_STB_H;
}

/*共陽數碼管資料格式轉換

輸入引數: SrcNum為0-9
pDst為轉換後的資料
seg為當前數碼管對應的sel管腳編號減1, 比如數碼管片選接到晶片的SEG2,那麼seg為1
dot為當前數碼管是否帶點顯示
*/
void convert(unsigned char SrcNum, unsigned char *pDst , unsigned char seg, unsigned char dot){
unsigned char table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

unsigned char i,uSrc;

if(dot == 0)
uSrc = table[SrcNum];
else
uSrc = table[SrcNum] | 0x80;

for(i=0; i<8; i++){ //一位一位移過去
if((uSrc & 0x01) == 1){//如果將要移過去的位是1,在對應的位置寫1,緊跟著後一位寫0
if(seg < 8){
pDst[2*i] = (1<<seg); //SEG<8,在地址的0、2、4、6、8、10、12、14寫入有效資料
pDst[2*i + 1] = 0;//在地址的1、3、5、7、9、11、13、15填零
}
else if(seg > 7){
pDst[2*i] = 0;//SEG>8,在地址的0、2、4、6、8、10、12、14填零
pDst[2*i + 1] = (1<<(seg - 8));//在地址的1、3、5、7、9、11、13、15寫入有效數字(9是左移1位,依次類推)
}
}
else{//如果將要移過去的位是0,在對應的位置寫0,緊跟著後一位寫0
pDst[2*i] = 0;
pDst[2*i + 1] = 0;
}
uSrc>>=1;//右移,移第二位
}

}

/*共陽數碼管資料格式轉換

特殊字元顯示
輸入引數: SrcNum為要顯示的資料,比如要顯示‘L’,用共陰的資料表示: h g f e d c b a 分別是 00111000(0x38)
pDst為轉換後的資料
seg為當前數碼管對應的sel管腳編號減1, 比如數碼管片選接到晶片的SEG2,那麼seg為1
a
f b
g
e c
d h
*/
void convert2(unsigned char SrcNum, unsigned char *pDst , unsigned char seg){
//uchar table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

unsigned char i,uSrc;

uSrc = SrcNum;
for(i=0; i<8; i++)
{
if((uSrc & 0x01) == 1)
{
if(seg < 8)
{
pDst[2*i] = (1<<seg);
pDst[2*i + 1] = 0;
}
else if(seg > 7)
{
pDst[2*i] = 0;
pDst[2*i + 1] = (1<<(seg - 8));
}
}
else
{
pDst[2*i] = 0;
pDst[2*i + 1] = 0;
}
uSrc>>=1;
}
}