找回密码
 立即注册
楼主: wuzhengmin

25.SPI读写W25X40CL - 按k1

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:47
  • 最近打卡:2025-10-21 08:57:14
已绑定手机

4

主题

356

回帖

627

积分

高级会员

积分
627
发表于 昨天 15:26 | 显示全部楼层
u8  Hex2Ascii(u8 dat)   //Hex 转Ascii
{
    dat &= 0x0f;
    if(dat < 10)    return (dat+'0');
    return (dat-10+'A');
}

代码解释
1.           dat &=0x0f;:这行代码的作用是将 dat 的高四位清零,只保留低四位。这通常用于提取一个字节中的低四位十六进制数。
2.           if(dat< 10) return (dat+'0');:如果 dat 的值小于 10,则返回对应的 ASCII 数字字符。例如,如果 dat 是 5,则返回 ‘5’。
3.       return(dat-10+'A');:如果 dat 的值大于等于 10,则返回对应的 ASCII 大写字母字符。例如,如果 dat 是 10,则返回 ‘A’,如果 dat 是 15,则返回 ‘F’。


回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:47
  • 最近打卡:2025-10-21 08:57:14
已绑定手机

4

主题

356

回帖

627

积分

高级会员

积分
627
发表于 昨天 15:32 | 显示全部楼层
/**************** ASCII码转BIN ****************************/
u8  CheckData(u8 dat)
{
    if((dat >= '0') && (dat <= '9'))        return (dat-'0');
    if((dat >= 'A') && (dat <= 'F'))        return (dat-'A'+10);
    return 0xff;
}



是用于检查字符 dat 是否是十六进制数字(0-9, a-f),并返回相应的数值。这通常是十六进制(Hex)到 ASCII 转换:
代码解释
1.   检查是否为数字(0-9
2.  if((dat>= '0') && (dat <= '9')) return (dat-'0');
这段代码检查 dat 是否是字符 ‘0’ 到 ‘9’ 之间的字符。如果是,则返回 dat 减去 ‘0’ 的 ASCII 值,这将得到对应的数字(例如,‘5’ - ‘0’ = 5)。
3.   检查是否为大写字母(A-F
4.  if((dat>= 'A') && (dat <= 'F'))
这段代码检查 dat 是否是字符 ‘A’ 到 ‘F’ 之间的字符。如果 dat 是这些字符之一,则需要进一步处理以返回对应的数值(例如,‘A’ 对应 10,‘B’ 对应 11,依此类推)。


回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:47
  • 最近打卡:2025-10-21 08:57:14
已绑定手机

4

主题

356

回帖

627

积分

高级会员

积分
627
发表于 昨天 15:47 | 显示全部楼层
/**************** 获取写入地址 ****************************/
u32 GetAddress(void)
{
    u32 address;
    u8  i,j;

    address = 0;
    if((RX2_Buffer[2] == '0') && (RX2_Buffer[3] == 'X'))
    {
        for(i=4; i<10; i++)
        {
            j = CheckData(RX2_Buffer);  //ASCII码转BIN,字符转数字
            if(j >= 0x10)   return 0x80000000;  //一位不可能大于16error
            address = (address << 4) + j;   //左移4位累加24位地址
        }
        return (address);  //返回得到的32位正确地址

    }
    return  0x80000000; //error
}

这样注释,很好理解吧?


回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:47
  • 最近打卡:2025-10-21 08:57:14
已绑定手机

4

主题

356

回帖

627

积分

高级会员

积分
627
发表于 昨天 16:15 | 显示全部楼层
/**************** 获取要读出数据的字节数 ****************************/
u8  GetDataLength(void)
{
    u8  i;
    u8  length;

    length = 0;
    for(i=11; i<RX2_Cnt; i++)  //最短的命令R 0X000100 是11位,后面开始是要读出几个数
    {
        if(CheckData(RX2_Buffer) >= 10)  break;  //10进制每一位不能大于10
        length = length * 10 + CheckData(RX2_Buffer); //每读到一位就把上次的进一位,累加得到要读的数据长度
    }
    return (length);
}



读这个之前,要先读串口2 中断函数:


//========================================================================
// 函数: void UART2_int (void) interrupt UART2_VECTOR
// 描述: UART2中断函数。
// 参数: nine.
// 返回: none.
// 版本: VER1.0
// 日期: 2014-11-28
// 备注:
//========================================================================
void UART2_int (void) interrupt 8
{
    if(S2RI)
    {
        S2RI = 0;    //Clear Rx flag
        RX2_Buffer[RX2_Cnt] = S2BUF;
        if(++RX2_Cnt >= UART2_BUF_LENGTH)   RX2_Cnt = 0;//RX2_Cnt在++
                  //直到假如超过UART2_BUF_LENGTH才清零,准备下一个轮回

        RX2_TimeOut = 5; //设置接受时间溢出
    }

    if(S2TI)
    {
        S2TI = 0;    //Clear Tx flag
        B_TX2_Busy = 0;
    }
}



要能从if(++RX2_Cnt >= UART2_BUF_LENGTH)   RX2_Cnt = 0;这句看出RX2_Cnt++
直到假如超过UART2_BUF_LENGTH才清零,准备下一个轮回




回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:47
  • 最近打卡:2025-10-21 08:57:14
已绑定手机

4

主题

356

回帖

627

积分

高级会员

积分
627
发表于 昨天 16:27 | 显示全部楼层
冲哥哥的第一个SPI的作业,快做完啦


回到主函数:


/********************* 主函数 *************************/
void main(void)
{
    WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    delay_ms(10);
    UART2_config(2);    // 选择波特率, 2: 使用Timer2做波特率, 其它值: 无效.
   
    EA = 1;                     //打开总中断
   
    PrintString2("命令设置:\r\n");
    PrintString2("E 0x001234            --> 扇区擦掉  十六进制地址\r\n");
    PrintString2("W 0x001234 1234567890 --> 写入操作  十六进制地址  写入内容\r\n");
    PrintString2("R 0x001234 10         --> 读出操作  十六进制地址  读出字节\r\n");
    PrintString2("C                     --> 如果检测不到PM25LV040/W25X40CL/W25Q80BV, 发送C强制允许操作.\r\n\r\n");

    SPI_init();
    FlashCheckID();
    FlashCheckID();
   
    if(!B_FlashOK)  PrintString2("未检测到PM25LV040/W25X40CL/W25Q80BV!\r\n");
    else
    {
        if(B_FlashOK == 1)
        {
            PrintString2("检测到PM25LV040!\r\n");
        }
        else if(B_FlashOK == 2)
        {
            PrintString2("检测到W25X40CL!\r\n");
        }
        else if(B_FlashOK == 3)
        {
            PrintString2("检测到W25Q80BV!\r\n");
        }
        PrintString2("制造商ID1 = 0x");
        UART2_TxByte(Hex2Ascii(PM25LV040_ID1 >> 4));
        UART2_TxByte(Hex2Ascii(PM25LV040_ID1));
        PrintString2("\r\n      ID2 = 0x");
        UART2_TxByte(Hex2Ascii(PM25LV040_ID2 >> 4));
        UART2_TxByte(Hex2Ascii(PM25LV040_ID2));
        PrintString2("\r\n   设备ID = 0x");
        UART2_TxByte(Hex2Ascii(PM25LV040_ID >> 4));
        UART2_TxByte(Hex2Ascii(PM25LV040_ID));
        PrintString2("\r\n");
    }

    while(1)
    {
        delay_ms(1);
               
        if(RX2_TimeOut > 0)
        {
            if(--RX2_TimeOut == 0)  //超时,则串口接收结束
            {
                if(RX2_Cnt > 0)
                {
                    RX2_Check();    //串口2处理数据
                }
                RX2_Cnt = 0;
            }
        }
    }
}


其实 还是在运行 RX2_Check();    //串口2处理数据
都能看懂的,自己写就不行啦
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:47
  • 最近打卡:2025-10-21 08:57:14
已绑定手机

4

主题

356

回帖

627

积分

高级会员

积分
627
发表于 昨天 16:58 | 显示全部楼层
到此为止,我们把STC的例子程序读了一遍,编译烧录进去试验箱:

要连接个STC-link1D ,自动下载(不用平时USB——CDC串口)

结果如下:




记得主频是22.1184 !

这个是UART2  不是USB-CDC ! 主频不到,就乱码一堆
截图202510211656295704.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:47
  • 最近打卡:2025-10-21 08:57:14
已绑定手机

4

主题

356

回帖

627

积分

高级会员

积分
627
发表于 昨天 17:00 | 显示全部楼层
反复试验了删除  读取  写入


都不会死机,初步实验成功!
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-10-22 01:24 , Processed in 0.149627 second(s), 78 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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