[KungFu8位 MCU]

KF8F4156 汇编和c混合编程示意

[复制链接]
868|1
手机看帖
扫描二维码
随时随地手机跟帖
l科科1987|  楼主 | 2017-7-31 15:58 | 显示全部楼层 |阅读模式
1.读取一个地址的flash数据
/***********************************************************************************
* 函数名     :FLASH_READ_ONE
* 函数功能:以设定地址开始,读取一个数的FLASH数据并返回结果
* 入口参数:起始地址
* 返回          :无
**********************************************************************************/
unsigned int FLASH_READ_ONE(unsigned int address)
{
#if  1          // 1 选用C语言表达  0 选用嵌汇编表达,嵌汇编效率更高,但提示传递参数未使用和函数无返回,可以忽略

        // FLASH_READ_BUF;  需要定义全局的该变量,获取值用于返回,或直接使用
        //; 参数的使用
        NVMADDRH=(unsigned char)(address>>8);
        NVMADDRL=(unsigned char)address;
        __asm
                ;//备份中断使能寄存器
                        BANKSEL _INTCTL
                        MOV                R1,_INTCTL
                ;//关闭中断,操作不可打断
                        CLR                _INTCTL,_AIE
                        JNB                _INTCTL,_AIE
                        JMP                $-2
                ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
                        MOV                R0,#0x30
                        MOV                R2,_OSCCTL
                        MOV                _OSCCTL,R0
                ;//硬件使能读操作
                        BANKSEL _NVMCTL0
                        MOV         R5,#0x81
                        MOV         _NVMCTL0,R5
                        NOPZ
                        NOPZ
                        NOPZ
                        NOPZ
                ;//时钟与中断使能的还原
                        MOV                _OSCCTL,R2
                        AND         R1,#0xC0        ;//中断使能仅关系高2位
                        ORL         INTCTL,R1
                ;//操作结果赋值到变量,用于返回
                        BANKSEL        _NVMDATAL
                        MOV        R6,_NVMDATAL
                        MOV        R7,_NVMDATAH
                        BANKSEL _FLASH_READ_BUF
                        MOV (_FLASH_READ_BUF),R6
                        MOV (_FLASH_READ_BUF+1),R7
        __endasm;
        return         FLASH_READ_BUF;
#else
        // 参数的传递使用  编译器自动变量 STK00  和 R0 ,其中R0为高位,返回使用STK00  和 R0 ,其中R0为高位
        __asm
        ;//传递操作地址
                BANKSEL _NVMADDRH
                MOV                _NVMADDRH,R0
                BANKSEL STK00
                MOV                R0,STK00
                BANKSEL _NVMADDRL
                MOV                _NVMADDRL,R0
        ;//备份中断使能寄存器
                BANKSEL _INTCTL
                MOV                R1,_INTCTL
        ;//关闭中断,操作不可打断
                CLR                _INTCTL,_AIE
                JNB                _INTCTL,_AIE
                JMP                $-2
        ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
                MOV                R0,#0x30
                MOV                R2,_OSCCTL
                MOV                _OSCCTL,R0
        ;//硬件使能读操作
                BANKSEL _NVMCTL0
                MOV         R5,#0x81
                MOV         _NVMCTL0,R5
                NOPZ
                NOPZ
                NOPZ
                NOPZ
        ;//时钟与中断使能的还原
                MOV                _OSCCTL,R2
                AND         R1,#0xC0        ;//中断使能仅关系高2位
                ORL         _INTCTL,R1
        ;//操作结果提供形式 整型数据返回结果使用  编译器自动变量 STK00  和 R0 ,其中R0为高位
                BANKSEL        _NVMDATAL
                MOV                R0,NVMDATAL
                BANKSEL STK00
                MOV                STK00,R0

                BANKSEL        _NVMDATAH
                MOV                R0,NVMDATAH
        __endasm;
#endif

}


l科科1987|  楼主 | 2017-7-31 15:59 | 显示全部楼层
2.写数据的flash
/***********************************************************************************
* 函数名     :FLASH_WRITE_FUN
* 函数功能:按块或按页写入数据到FLASH,个数参数只能为16,32 ,地址必须为块的首地址 如十六进制下结尾00 20 40 60 80 A0 C0 E0
*                         如果地址不是页的首地址,必须确定后续块结果为0xFFFF,或前面操作过块首写,使后续块值被0xFFFF,否则写结果异常。
* 入口参数:待写地址,待写地址的数据
* 返回          :无
* 写时间说明:除去代码,以整页FLASH为例,操作完第一块需要6ms,另外3块需要3ms。即第一块执行整页的擦除后写自身块,其他块直接写。
**********************************************************************************/
void FLASH_WRITE_FUN(unsigned int address,unsigned char length)
{
#if 1             //  1时效率比0小   1 使用传递参数   0 按编译器全嵌汇编实现,但编译提示参数未使用,可以忽略
        //; 参数的使用
        NVMADDRH=(unsigned char) (address>>8);
        NVMADDRL=address;

        __asm
        ;//备份中断使能寄存器
                BANKSEL _INTCTL
                MOV                R1,_INTCTL
        ;//关闭中断,操作不可打断
                CLR                _INTCTL,_PUIE
                CLR                _INTCTL,_AIE
                JNB                _INTCTL,_AIE
                JMP                $-2
        ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
                MOV                R0,#0x30
                MOV                R2,_OSCCTL
                MOV                _OSCCTL,R0
        ;//读取结果的存放起始RAM地址,即数组缓存区  FLASH_BUFFER[x]
                MOV                R3,#_FLASH_BUFFER
        __endasm;

        while(length--)                // 仅使用R0,不改变R1
        {
                __asm

                ;//加载待写数据
                BANKSEL _FLASH_BUFFER
                LD                R6,[R3]
                INC                R3
                LD                R7,[R3]
                INC                R3
                BANKSEL _NVMDATAH
                MOV _NVMDATAH,R7
                MOV _NVMDATAL,R6
                ;//硬件写
                MOV         R5 ,#0x84
                MOV         _NVMCTL0,R5
                MOV         R5,#0x69
                MOV         _NVMCTL1,R5
                MOV         R5,#0x96
                MOV         _NVMCTL1,R5
                SET         _NVMCTL0 , 1        ;// 写存在高压,高压还原添加空指令确保后续运行正常
                NOPZ
                NOPZ
                NOPZ
                NOPZ
                NOPZ
                NOPZ                                                ;// 建议10条,至少2条
                NOPZ
                NOPZ
                NOPZ
                NOPZ
                MOV         R5,#0X80
                MOV         _NVMCTL0,R5
                ;//指向下一操作地址,这里不考虑高位,特性要求只能操作一页内的数据,不能跨页
                BANKSEL _NVMADDRL
                INC                _NVMADDRL
                __endasm;
        }

        __asm
                ;//时钟与中断使能的还原
                BANKSEL _OSCCTL
                MOV                _OSCCTL,R2
                AND         R1,#0xC0        ;//中断使能仅关系高2位
                ORL         _INTCTL,R1
        __endasm;
#else
        // 参数1的传递使用  编译器自动变量 STK00  和 R0 ,其中R0为高位
        // 参数2的传递使用  编译器自动变量 STK01
        // 整体实现的嵌汇编会提示参数未被使用,可以忽略
__asm
        ;//传递操作的地址(块首)
        BANKSEL _NVMADDRH
        MOV                _NVMADDRH,R0
        BANKSEL STK00
        MOV                R0,STK00
        BANKSEL _NVMADDRL
        MOV                _NVMADDRL,R0
        ;//备份中断使能寄存器
        BANKSEL        _INTCTL
        MOV                R1,_INTCTL
        ;//关闭中断,操作不可打断
        CLR                _INTCTL,_PUIE
        CLR                _INTCTL,_AIE
        JNB                _INTCTL,_AIE
        JMP                $-2
        ;//时钟频率备份及降频操作,建议降频到1M,此时中断已被关
        MOV                R0,#0x30
        MOV                R2,_OSCCTL
        MOV                _OSCCTL,R0
        ;//待写数据的存放起始RAM地址,即数组缓存区  FLASH_BUFFER[x]
        MOV                R0,#_FLASH_BUFFER

FALSH_WRITE_PAGE_LOOP:
        ;//加载待写数据
        BANKSEL _FLASH_BUFFER
        LD                R6,[R0]
        INC                R0
        LD                R7,[R0]
        INC                R0

        BANKSEL _NVMDATAH
        MOV _NVMDATAH,R7
        MOV _NVMDATAL,R6

        ;//硬件写
        MOV         R5 ,#0x84
        MOV         _NVMCTL0,R5
        MOV         R5,#0x69
        MOV         _NVMCTL1,R5
        MOV         R5,#0x96
        MOV         _NVMCTL1,R5
        SET         _NVMCTL0 , 1        ;// 写存在高压,高压还原添加空指令确保后续运行正常
        NOPZ
        NOPZ
        NOPZ
        NOPZ
        NOPZ
        NOPZ                                                ;// 建议10条,至少2条
        NOPZ
        NOPZ
        NOPZ
        NOPZ
        MOV         R5,#0X80
        MOV         _NVMCTL0,R5
        ;//指向下一操作地址,这里不考虑高位,特性要求只能操作一页内的数据,不能跨页
        BANKSEL _NVMADDRL
        INC                _NVMADDRL

        BANKSEL STK01
        DECJZ        STK01
        JMP                FALSH_WRITE_PAGE_LOOP

        ;//时钟与中断使能的还原
        BANKSEL _OSCCTL
        MOV                _OSCCTL,R2
        AND         R1,#0xC0        ;//中断使能仅关系高2位
        ORL         _INTCTL,R1
__endasm;
#endif
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

214

帖子

1

粉丝