搜索
bottom↓
回复: 17

利用STM32硬件SPI驱动MAX7456

[复制链接]

出0入0汤圆

发表于 2009-9-2 21:28:39 | 显示全部楼层 |阅读模式
查资料时,有感于坛子里面关于这个片子的参考程序比较少,就用“最热门”的STM32做了个驱动,官方2.02库

直接贴代码了:

//Spi_Max7456.h



#include "stm32f10x_lib.h"
#include "stm32f10x_spi.h"
#define MAX7456_SPI          SPI2//利用SPI2传输数据

#define MAX7456_SPICLK       RCC_APB1Periph_SPI2  //spi2时钟
#define MAX7456_PCLK         RCC_APB2Periph_GPIOB //spi数据与时钟控制口
#define MAX7456_SPI_PORT     GPIOB
#define MAX7456_SCK          GPIO_Pin_13
#define MAX7456_MOSI         GPIO_Pin_15
#define MAX7546_CS           GPIO_Pin_12
#define MAX7456_MISO         GPIO_Pin_14

//MAX7456写寄存器
#define RADD1         0X80 //对于<0x10写地址,在读的时候要加0X80

#define VM0           0X00 //视频模式0寄存器
#define VM1           0X01 //视频模式1寄存器
#define HOS           0X02 //水平位置寄存器
#define VOS           0X03 //垂直位置寄存器
#define DMM           0X04 //显示存储器模式寄存器
#define DMAH          0X05 //显示存储器地址高位寄存器
#define DMAL          0X06 //显示存储器地址低位寄存器
#define DMDI          0X07 //显示存储器数据输入寄存器
#define CMM           0X08 //字符存储器模式寄存器
#define CMAH          0X09 //字符存储器地址高位寄存器
#define CMAL          0X0A //字符存储器地址低位寄存器
#define CMDI          0X0B //字符存储器数据输入寄存器
#define OSDM          0X0C //OSD插入复用寄存器
#define RB            0X10 //第N行亮度寄存器,0-13  0-15 根据不同制式 0X10+RB0-15
#define OSDBL_W_ADD   0X6C //OSD黑电平寄存器
#define OSDBL_R_ADD   0XEC //读寄存器地址
#define STAT          0XA0 //状态寄存器(只读) 实际上可以读任何一个0XA0-AF
#define DMDO          0XB0 //显示存储器输出寄存器(只读)
#define CMMO          0XC0 //字符存储器输出寄存器(只读)


void MAX7456_SYS_Init(void);
u8 MAX7456_Read_Reg(u8 add);
void MAX7456_Write_Char(u16 add,u8 chr);
void MAX7456_WriteAtt_Char(u16 add,u8 attribute);
void MAX7456_Write_Char_XY(u8 X,u8 Y,u8 chr);
void MAX7456_WriteAtt_XY(u8 X,u8 Y,u8 chr);
void MAX7456_Clear(void);
void MAX7456_Write_ASCII_Chr(u8 X,u8 Y,u8 chr);
void MAX7456_Write_ASCII_Char(u16 address, u8 c);
void MAX7456_Write_ASCII_String(u8 X,u8 Y,u8 *Str);
void Max7456_Learn_Char(u8 number, u8 *data);
void Max7456_Write_CustomChar(void);
void Max7456_Write_FileChar(void);
void Max7456_Display_AllChar(void);
void Max7456_Check_Custom(void);





//spi_max7456.c
#include "SPI_MAX7456.h"

#include "Chartar_Max7456.h"// 包含字库文件



#define MAX7456_CS_Low()         GPIO_ResetBits(MAX7456_SPI_PORT, MAX7546_CS)
#define MAX7456_CS_Hight()       GPIO_SetBits(MAX7456_SPI_PORT, MAX7546_CS)
#define MAX7456_StartSpi()       MAX7456_CS_Low()  //开始SPI
#define MAX7456_EndSpi()        MAX7456_CS_Hight() //结束SPI

GPIO_InitTypeDef GPIO_InitStructure_MAX7456;//GPIO操作结构体
SPI_InitTypeDef SPI_InitStructure_MAX7456;//SPI结构体


//========================================================================
// 函数: void ZSBW_ARW_PORT_Init(void)
// 描述: 初始化操作端口和IO方向
// 参数: 无
// 返回: 无
// 备注:
// 版本:
//            First version
//========================================================================
void MAX7456_PORT_Init(void)
{
        RCC_APB2PeriphClockCmd(MAX7456_PCLK,ENABLE);
        RCC_APB1PeriphClockCmd(MAX7456_SPICLK,ENABLE);
        //
        GPIO_InitStructure_MAX7456.GPIO_Pin=MAX7456_SCK|MAX7456_MOSI|MAX7456_MISO;
        GPIO_InitStructure_MAX7456.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIO_InitStructure_MAX7456.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(MAX7456_SPI_PORT,&GPIO_InitStructure_MAX7456);
        //
        GPIO_InitStructure_MAX7456.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_InitStructure_MAX7456.GPIO_Pin=MAX7546_CS;
        GPIO_Init(MAX7456_SPI_PORT,&GPIO_InitStructure_MAX7456);
}

//========================================================================
// 函数: void ZSBW_ARW_PORT_Init(void)
// 描述: 初始化的SPI的相位,时钟等属性
// 参数: 无
// 返回: 无
// 备注:
// 版本:
//            First version
//========================================================================
void MAX7456_SPI_Init(void)
{
        //
       
        MAX7456_CS_Hight();
        //
        SPI_InitStructure_MAX7456.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
        SPI_InitStructure_MAX7456.SPI_Mode=SPI_Mode_Master;
        SPI_InitStructure_MAX7456.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_4;//max7456最高速率10M SPI最高时钟P/2=36M
        SPI_InitStructure_MAX7456.SPI_CPHA=SPI_CPHA_1Edge;
        SPI_InitStructure_MAX7456.SPI_CPOL=SPI_CPOL_Low;
        SPI_InitStructure_MAX7456.SPI_NSS=SPI_NSS_Soft;
        SPI_InitStructure_MAX7456.SPI_DataSize=SPI_DataSize_8b;
        SPI_InitStructure_MAX7456.SPI_FirstBit=SPI_FirstBit_MSB;
        SPI_InitStructure_MAX7456.SPI_CRCPolynomial=7;
        SPI_Init(MAX7456_SPI, &SPI_InitStructure_MAX7456);
        //
        SPI_Cmd(MAX7456_SPI,ENABLE);

}

//========================================================================
// 函数: void ZSBW_ARW_WriteByte(u8 Data)
// 描述: 写入一个字节的数据到
// 参数: 写入的字节
// 返回: 无
// 备注: 无
// 版本:
//           First version
//========================================================================
u8 MAX7456_SPI_WriteByte(u8 Data)
{
        /* Wait for SPI2 Tx buffer empty */
        while (SPI_I2S_GetFlagStatus(MAX7456_SPI, SPI_I2S_FLAG_TXE) == RESET);
    /* Send SPI2 data */
    SPI_I2S_SendData(MAX7456_SPI, Data);

        while (SPI_I2S_GetFlagStatus(MAX7456_SPI, SPI_I2S_FLAG_RXNE) == RESET);
    /* Read SPI2 received data */
    Data = SPI_I2S_ReceiveData(MAX7456_SPI);

    return Data;
}


//========================================================================
// 函数: void ZSBW_ARW_WriteByte(u8 Data)
// 描述: 从MAX7456读取一个字节
// 参数: 地址
// 返回: 无
// 备注: 无
// 版本:
//           First version
//========================================================================
u8 MAX7456_SPI_ReadByte(void)
{
        u8 Data=0;
        /* Wait for SPI2 Tx buffer empty */
        while (SPI_I2S_GetFlagStatus(MAX7456_SPI, SPI_I2S_FLAG_TXE) == RESET);
    /* Send SPI2 data */
    SPI_I2S_SendData(MAX7456_SPI, Data);

        while (SPI_I2S_GetFlagStatus(MAX7456_SPI, SPI_I2S_FLAG_RXNE) == RESET);
    /* Read SPI2 received data */
    Data = SPI_I2S_ReceiveData(MAX7456_SPI);

    return Data;
}

//延时函数
void MAX7456_Delay_uS(void)
{       
   u8 i=100; //
   while(i)
   {
     i--;
   }
}

//延时毫秒
void MAX7456_Delay_mS(u32 mS)
{
        u32 i=0;
        for(i=0;i<mS;i++)
        {
                MAX7456_Delay_uS();
        }
}

//MAX7456写入一个寄存器
void MAX7456_Write_Reg(u8 add,u8 data)
{
        MAX7456_StartSpi();
       
        MAX7456_SPI_WriteByte(add);//写入地址
        MAX7456_SPI_WriteByte(data);//写入数据

        MAX7456_EndSpi();
}

//MAX7456读入一个寄存器
u8 MAX7456_Read_Reg(u8 add)
{
        u8 Data=0;
        MAX7456_StartSpi();
       
        MAX7456_SPI_WriteByte(add);//写入地址
        Data=MAX7456_SPI_ReadByte();//读出数据

        MAX7456_EndSpi();

        return Data;
}

//========================================================================
// 函数: void MAX7456_SYS_Init(void)
// 描述: 初始化MAX7456
// 参数: 无
// 返回: 无
// 备注: 无
// 版本:
//           First version
//========================================================================
void MAX7456_SYS_Init(void)
{
        //
        MAX7456_PORT_Init();//GPIO初始化
        //
        MAX7456_SPI_Init();//SPI初始化

        //
        MAX7456_Write_Reg(VM0,0x00);//关闭视频模式

        //写入文件所有自定义字符 ,每个芯片未初始化前要调用。
        //Max7456_Write_FileChar();

        MAX7456_Delay_mS(1000);//延时

        MAX7456_Write_Reg(VM0,0X40);//设置为PAL模式

        MAX7456_Write_Reg(DMM,0X04);//清理显存
        //
        MAX7456_Delay_mS(1000);//延时

        MAX7456_Write_Reg(DMM,0X40);//设置为8bit模式

        MAX7456_Delay_mS(1000);

        MAX7456_Write_Reg(VM0,0X48);
        MAX7456_Delay_mS(1000);

        MAX7456_Write_Reg(VM1,0X00);
        MAX7456_Delay_mS(1000);

        MAX7456_Write_Reg(OSDBL_W_ADD,(MAX7456_Read_Reg(OSDBL_R_ADD)|0X10));

       
        MAX7456_Write_Reg(OSDM,0x2D);

}



void MAX7456_Write_Char(u16 add,u8 chr)
{
        //
        MAX7456_Write_Reg(DMAH, (add&0XFF00)>>8);
        MAX7456_Write_Reg(DMAL, (add&0XFF));
        MAX7456_Write_Reg(DMDI,chr);
}



void MAX7456_WriteAtt_Char(u16 add,u8 attribute)
{
        //
        MAX7456_Write_Reg(DMAH, ((add&0XFF00)>>8)|2);
        MAX7456_Write_Reg(DMAL, (add&0XFF));
        MAX7456_Write_Reg(DMDI,attribute);
}


void MAX7456_Write_Char_XY(u8 X,u8 Y,u8 chr)
{
        //
        u16 add=0;
        add=((u16)Y)*30+X;
        MAX7456_Write_Char(add,chr);
}


void MAX7456_WriteAtt_XY(u8 X,u8 Y,u8 chr)
{
        //
        u16 add=0;
        add=((u16)Y)*30+X;
        MAX7456_WriteAtt_Char(add,chr);
}



void MAX7456_Clear(void)
{
        u16 memory_address = 0,i=0;
    for (i = 0; i < 480; i++)
        MAX7456_Write_Char(memory_address++, 0);
}


void MAX7456_Write_ASCII_Char(u16 address, u8 c)
{
    if (c == 32) c = 0; // remap space
    else if (c > 48 && c <= 57) c -= 48; // remap numbers
    else if (c == '0') c = 10; // remap zero
    else if (c >= 65 && c <= 90) c -= 54; // remap big letters
    else if (c >= 97 && c <= 122) c -= 60; // remap small letters
    else if (c == '(') c = 63; // remap
    else if (c == ')') c = 64; // remap
    else if (c == '.') c = 65; // remap
    else if (c == '?') c = 66; // remap
    else if (c == ';') c = 67; // remap
    else if (c == ':') c = 68; // remap
    else if (c == ',') c = 69; // remap
    else if (c == '\'') c = 70; // remap
    else if (c == '/') c = 71; // remap
    else if (c == '"') c = 72; // remap
    else if (c == '-') c = 73; // remap minus
    else if (c == '<') c = 74; // remap
    else if (c == '>') c = 75; // remap
    else if (c == '@') c = 76; // remap
    MAX7456_Write_Char(address, c);
}


void MAX7456_Write_ASCII_Chr(u8 X,u8 Y,u8 chr)
{
        MAX7456_Write_ASCII_Char(((X++)+(((u16)Y*30))),chr);
}

void MAX7456_Write_ASCII_String(u8 X,u8 Y,u8 *Str)
{
        while(*Str)
        {
                MAX7456_Write_ASCII_Char(((X++)+(((u16)Y*30))),*Str);
                Str++;
        }
}


void Max7456_Learn_Char(u8 number, u8 *data)
{
        u8 i=0;
    // select character to write (CMAH)
    MAX7456_Write_Reg(CMAH, number);

    for (i = 0; i < 54; i++) {
        // select 4pixel byte of char (CMAL)
        MAX7456_Write_Reg(CMAL, i);

        // write 4pixel byte of char (CMDI)
        MAX7456_Write_Reg(CMDI, data);
    }

    // write to the NVM array from the shadow RAM (CMM)
    MAX7456_Write_Reg(CMM, 0xa0);

    // according to maxim writing to nvram takes about 12ms, lets wait longer
    MAX7456_Delay_mS(1200);//修改延时看能否写入
}


//从字库文件中提取字符写入MAX7456
void Max7456_Write_FileChar(void)
{

        u16 i=0;
        for(i=0;i<=255;i++)
                Max7456_Learn_Char(i,chars);

}

//将字库中的文件显示出来,以测试使用
void Max7456_Display_AllChar(void)
{
        u16 i=0;
        for(i=0;i<25;i++)
                MAX7456_Write_Char_XY(i, 1, i);
        for(i=25;i<50;i++)
                MAX7456_Write_Char_XY(i-25, 2, i);
        for(i=50;i<75;i++)
                MAX7456_Write_Char_XY(i-50, 3, i);

        for(i=75;i<100;i++)
                MAX7456_Write_Char_XY(i-75, 4, i);
        for(i=100;i<125;i++)
                MAX7456_Write_Char_XY(i-100, 5, i);
        for(i=125;i<150;i++)
                MAX7456_Write_Char_XY(i-125, 6, i);

        for(i=150;i<175;i++)
                MAX7456_Write_Char_XY(i-150, 7, i);
        for(i=175;i<200;i++)
                MAX7456_Write_Char_XY(i-175, 8, i);
        for(i=200;i<225;i++)
                MAX7456_Write_Char_XY(i-200, 9, i);

        for(i=225;i<250;i++)
                MAX7456_Write_Char_XY(i-225, 10, i);

        for(i=250;i<=255;i++)
                MAX7456_Write_Char_XY(i-250, 11, i);
}


以上程序,MAX7456功能函数参考并抄袭了:

http://www.mylifesucks.de/oss/c-osd/

字库生成用的如下网站的脚本

http://www.mylifesucks.de/tools/max7456/

字库文件ourdev_477183.txt(文件大小:2K) (原文件名:Spi_Max7456.h.txt)

硬件配置:STM32F103XXX,外部8M晶振,PLL9
编译调试环境:Keil For ARM/Ulink2

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2009-9-17 18:11:33 | 显示全部楼层
完成一个挑战,支持!

出0入0汤圆

发表于 2009-10-9 17:28:09 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-9 10:28:02 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-21 10:43:32 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-9-24 23:48:38 | 显示全部楼层
楼主啊,7456哪里有搞啊,我翻遍淘宝都只看到一家,你在哪里整的啊

出0入0汤圆

发表于 2011-1-15 18:10:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-17 16:36:09 | 显示全部楼层
牛人

出0入0汤圆

发表于 2012-4-23 10:51:52 | 显示全部楼层
max7456 mark

出0入0汤圆

发表于 2012-4-25 00:22:15 | 显示全部楼层
我也用STM32驱动成功,不过我的是模拟SPI的

出0入0汤圆

发表于 2012-5-1 23:23:44 | 显示全部楼层
LZ最近坛子下载不了,可不可以给我发个字库文件,163.com的flex,谢谢,(留箱子是违规的,但请大家不要申张,情有可原吗

出0入4汤圆

发表于 2015-1-5 11:06:58 | 显示全部楼层
支持 32个赞

出0入0汤圆

发表于 2015-1-14 20:44:13 | 显示全部楼层
谢谢LZ分享,看stm32 datasheet时看到一段话:

Full-duplex transmit and receive procedure inmaster or slave mode (BIDIMODE=0 and
RXONLY=0)
The software has to follow this procedure to transmit and receive data (see Figure 240and
Figure 241):
1. Enable the SPI by setting the SPE bit to 1.
2.  Write the first data item to be transmitted into the SPI_DR register (this clears the TXE
flag).
3.  Wait until TXE=1 and write the second data item to be transmitted. Then wait until
RXNE=1 and read the SPI_DR to get the first received data item (this clears the RXNE
bit). Repeat this operation for each data item to be transmitted/received until the n–1
received data.
4.  Wait until RXNE=1 and read the last received data.
5.  Wait until TXE=1 and then wait until BSY=0 before disabling the SPI.

在读取数据时的写数据只是为了提供一个clk,相当于dummy data,看了下LZ的SPI读写函数恍然大悟!

谢谢......

出0入0汤圆

发表于 2015-5-18 08:13:38 | 显示全部楼层
感谢楼主分享    打算看看OSD相关资料    学习了  。。。

出0入0汤圆

发表于 2015-8-13 20:36:50 | 显示全部楼层
这东西怎么生成#include "Chartar_Max7456.h"// 包含字库文件   这个头文件 能说明一下吗?
    还有能给个程序学习一下吗?

出0入0汤圆

发表于 2015-8-13 21:01:04 | 显示全部楼层
MAX7456_Write_ASCII_Char这个函数写得很醉

出0入0汤圆

发表于 2015-10-6 12:11:15 | 显示全部楼层
以前拿51的单片机做过,mark下

出0入0汤圆

发表于 2016-4-18 21:34:35 | 显示全部楼层
你好   这个能直接下载测试么   也想做一个
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-23 21:20

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表