tl;dr - Just quickly looking at your code, you only seem to be writing the first part of the address to PPU_ADDRESS - you need to write the whole 16 bit address. Secondly, presumably because it's a demo, your code has movement functions being called before the update to CHR-RAM - I would recommend you don;t do this, and call CHR-RAM updates first, at the very top, as NMI update time is limitedand if it overruns, you will get horrible graphical glitches to your tiles.
Hi Diskover, the game you're porting looks ace! I look forward to playing it!
I've done quite a lot of CHR-RAM updating for animations - 
First I made a lookup table of the address of the graphic I want to write in to CHR-RAM, and the address it should be written to - here's an excerpt:
Code:
;address in rom high, address in rom low, destination address high, destination address low
tile_lookup:
.byte <spike1_chr, >spike1_chr, 22, 16
 .byte <spike2_chr, >spike2_chr, 22, 16
 .byte <spike3_chr, >spike3_chr, 22, 16
.byte <coin1_chr, >coin1_chr, 18, 16
.byte <coin2_chr, >coin2_chr, 18, 16
.byte <coin3_chr, >coin3_chr, 18, 16
.byte <coin4_chr, >coin4_chr, 18, 16
.byte <fivecoin1_chr, >fivecoin1_chr, 18, 32
.byte <fivecoin2_chr, >fivecoin2_chr, 18, 32
.byte <fivecoin3_chr, >fivecoin3_chr, 18, 32
.byte <fivecoin4_chr, >fivecoin4_chr, 18, 32
Secondly, I wrote a function in assembly to load the tile when given the name as a parameter:
Code:
_copy_tile:
 tay
 lda tile_lookup, y ; load the source address into a pointer in zero page
 sta src
 iny
 lda tile_lookup,y
 sta src+1
 iny
 lda tile_lookup,y
  sta PPUADDR  ; load the destination address into the PPU
  iny
  lda tile_lookup,y
  sta PPUADDR
  ldy #0
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
   
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
   
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
   
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  rts   
Thirdly, I then export this from the assembly, forthly I write a function header in C, and then finally call it in C like this:
Code:
copy_tile(chr_heart1);
That's it - just make sure you're calling copy_tile in the NMI.
Hopefully this is of some help, if not let me know!